diff --git a/tests/sys/fs/fuse/access.cc b/tests/sys/fs/fuse/access.cc index 9e8e896915c1..8ce010289246 100644 --- a/tests/sys/fs/fuse/access.cc +++ b/tests/sys/fs/fuse/access.cc @@ -39,7 +39,13 @@ extern "C" { using namespace testing; -class Access: public FuseTest {}; +class Access: public FuseTest { +public: +void expect_lookup(const char *relpath, uint64_t ino) +{ + FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, 1); +} +}; /* TODO: test methods for the default_permissions mount option */ @@ -52,12 +58,7 @@ TEST_F(Access, DISABLED_eaccess) uint64_t ino = 42; mode_t access_mode = X_OK; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - })); + expect_lookup(RELPATH, ino); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_ACCESS && @@ -81,12 +82,7 @@ TEST_F(Access, DISABLED_ok) uint64_t ino = 42; mode_t access_mode = R_OK; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - })); + expect_lookup(RELPATH, ino); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_ACCESS && diff --git a/tests/sys/fs/fuse/create.cc b/tests/sys/fs/fuse/create.cc index e29fc8b66438..0d02a4701e0a 100644 --- a/tests/sys/fs/fuse/create.cc +++ b/tests/sys/fs/fuse/create.cc @@ -295,14 +295,7 @@ TEST_F(Create, DISABLED_entry_cache_negative_purge) ASSERT_LE(0, fd) << strerror(errno); /* Finally, a subsequent lookup should query the daemon */ - EXPECT_LOOKUP(1, RELPATH).Times(1) - .WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->header.error = 0; - out->body.entry.nodeid = ino; - out->body.entry.attr.mode = S_IFREG | mode; - SET_OUT_HEADER_LEN(out, entry); - })); + expect_lookup(RELPATH, ino, S_IFREG | mode, 1); ASSERT_EQ(0, access(FULLPATH, F_OK)) << strerror(errno); /* Deliberately leak fd. close(2) will be tested in release.cc */ diff --git a/tests/sys/fs/fuse/flush.cc b/tests/sys/fs/fuse/flush.cc index 98ffc88bd3c8..9f071b8a8929 100644 --- a/tests/sys/fs/fuse/flush.cc +++ b/tests/sys/fs/fuse/flush.cc @@ -40,8 +40,6 @@ using namespace testing; class Flush: public FuseTest { -const static uint64_t FH = 0xdeadbeef1a7ebabe; - public: void expect_flush(uint64_t ino, int times, ProcessMockerT r) { @@ -49,58 +47,16 @@ void expect_flush(uint64_t ino, int times, ProcessMockerT r) ResultOf([=](auto in) { return (in->header.opcode == FUSE_FLUSH && in->header.nodeid == ino && - in->body.flush.fh == Flush::FH); + in->body.flush.fh == FH); }, Eq(true)), _) ).Times(times) .WillRepeatedly(Invoke(r)); } -void expect_getattr(uint64_t ino) -{ - /* Until the attr cache is working, we may send an additional GETATTR */ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_GETATTR && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, attr); - out->body.attr.attr.ino = ino; // Must match nodeid - out->body.attr.attr.mode = S_IFREG | 0644; - })); - -} - void expect_lookup(const char *relpath, uint64_t ino) { - EXPECT_LOOKUP(1, relpath).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - out->body.entry.attr_valid = UINT64_MAX; - })); -} - -void expect_open(uint64_t ino, int times) -{ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_OPEN && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).Times(times) - .WillRepeatedly(Invoke([](auto in, auto out) { - out->header.unique = in->header.unique; - out->header.len = sizeof(out->header); - SET_OUT_HEADER_LEN(out, open); - out->body.open.fh = Flush::FH; - })); - + FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, 1); } /* @@ -130,8 +86,8 @@ TEST_F(Flush, DISABLED_dup) int fd, fd2; expect_lookup(RELPATH, ino); - expect_open(ino, 1); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); expect_flush(ino, 2, ReturnErrno(0)); expect_release(); @@ -161,8 +117,8 @@ TEST_F(Flush, DISABLED_eio) int fd; expect_lookup(RELPATH, ino); - expect_open(ino, 1); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); expect_flush(ino, 1, ReturnErrno(EIO)); expect_release(); @@ -182,8 +138,8 @@ TEST_F(Flush, DISABLED_flush) int fd; expect_lookup(RELPATH, ino); - expect_open(ino, 1); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); expect_flush(ino, 1, ReturnErrno(0)); expect_release(); diff --git a/tests/sys/fs/fuse/fsync.cc b/tests/sys/fs/fuse/fsync.cc index ec828b3d8031..01b568acb52b 100644 --- a/tests/sys/fs/fuse/fsync.cc +++ b/tests/sys/fs/fuse/fsync.cc @@ -50,7 +50,6 @@ using namespace testing; class Fsync: public FuseTest { public: -const static uint64_t FH = 0xdeadbeef1a7ebabe; void expect_fsync(uint64_t ino, uint32_t flags, int error) { EXPECT_CALL(*m_mock, process( @@ -65,79 +64,14 @@ void expect_fsync(uint64_t ino, uint32_t flags, int error) ).WillOnce(Invoke(ReturnErrno(error))); } -void expect_getattr(uint64_t ino) -{ - /* Until the attr cache is working, we may send an additional GETATTR */ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_GETATTR && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, attr); - out->body.attr.attr.ino = ino; // Must match nodeid - out->body.attr.attr.mode = S_IFREG | 0644; - out->body.attr.attr_valid = UINT64_MAX; - })); -} - void expect_lookup(const char *relpath, uint64_t ino) { - EXPECT_LOOKUP(1, relpath).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - out->body.entry.attr_valid = UINT64_MAX; - })); -} - -void expect_open(uint64_t ino) -{ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_OPEN && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->header.len = sizeof(out->header); - SET_OUT_HEADER_LEN(out, open); - out->body.open.fh = FH; - })); -} - -void expect_release(uint64_t ino) -{ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_RELEASE && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).WillOnce(Invoke(ReturnErrno(0))); + FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, 1); } void expect_write(uint64_t ino, uint64_t size, const void *contents) { - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - const char *buf = (const char*)in->body.bytes + - sizeof(struct fuse_write_in); - - return (in->header.opcode == FUSE_WRITE && - in->header.nodeid == ino && - 0 == bcmp(buf, contents, size)); - }, Eq(true)), - _) - ).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, write); - out->body.write.size = size; - })); + FuseTest::expect_write(ino, 0, size, size, 0, contents); } }; @@ -156,8 +90,8 @@ TEST_F(Fsync, DISABLED_aio_fsync) int fd; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); expect_write(ino, bufsize, CONTENTS); expect_fsync(ino, 0, 0); @@ -190,8 +124,8 @@ TEST_F(Fsync, close) int fd; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); expect_write(ino, bufsize, CONTENTS); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { @@ -209,7 +143,7 @@ TEST_F(Fsync, close) }, Eq(true)), _) ).Times(0); - expect_release(ino); + expect_release(ino, 1, 0); fd = open(FULLPATH, O_RDWR); ASSERT_LE(0, fd) << strerror(errno); @@ -228,8 +162,8 @@ TEST_F(Fsync, DISABLED_eio) int fd; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); expect_write(ino, bufsize, CONTENTS); expect_fsync(ino, FUSE_FSYNC_FDATASYNC, EIO); @@ -253,8 +187,8 @@ TEST_F(Fsync, DISABLED_fdatasync) int fd; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); expect_write(ino, bufsize, CONTENTS); expect_fsync(ino, FUSE_FSYNC_FDATASYNC, 0); @@ -278,8 +212,8 @@ TEST_F(Fsync, DISABLED_fsync) int fd; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); expect_write(ino, bufsize, CONTENTS); expect_fsync(ino, 0, 0); @@ -303,8 +237,8 @@ TEST_F(Fsync, DISABLED_fsync_metadata_only) mode_t mode = 0755; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_SETATTR); @@ -335,8 +269,8 @@ TEST_F(Fsync, nop) int fd; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); fd = open(FULLPATH, O_WRONLY); ASSERT_LE(0, fd) << strerror(errno); @@ -346,4 +280,4 @@ TEST_F(Fsync, nop) /* Deliberately leak fd. close(2) will be tested in release.cc */ } - +// TODO: ENOSYS test diff --git a/tests/sys/fs/fuse/fsyncdir.cc b/tests/sys/fs/fuse/fsyncdir.cc index 8cf624cbe635..bc7363377315 100644 --- a/tests/sys/fs/fuse/fsyncdir.cc +++ b/tests/sys/fs/fuse/fsyncdir.cc @@ -50,7 +50,6 @@ using namespace testing; class FsyncDir: public FuseTest { public: -const static uint64_t FH = 0xdeadbeef1a7ebabe; void expect_fsyncdir(uint64_t ino, uint32_t flags, int error) { EXPECT_CALL(*m_mock, process( @@ -67,29 +66,7 @@ void expect_fsyncdir(uint64_t ino, uint32_t flags, int error) void expect_lookup(const char *relpath, uint64_t ino) { - EXPECT_LOOKUP(1, relpath).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFDIR | 0755; - out->body.entry.nodeid = ino; - out->body.entry.attr_valid = UINT64_MAX; - })); -} - -void expect_opendir(uint64_t ino) -{ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_OPENDIR && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->header.len = sizeof(out->header); - SET_OUT_HEADER_LEN(out, open); - out->body.open.fh = FH; - })); + FuseTest::expect_lookup(relpath, ino, S_IFDIR | 0755, 1); } }; diff --git a/tests/sys/fs/fuse/getattr.cc b/tests/sys/fs/fuse/getattr.cc index 630bdf552944..c107c74bc870 100644 --- a/tests/sys/fs/fuse/getattr.cc +++ b/tests/sys/fs/fuse/getattr.cc @@ -45,7 +45,6 @@ TEST_F(Getattr, DISABLED_attr_cache) const char FULLPATH[] = "mountpoint/some_file.txt"; const char RELPATH[] = "some_file.txt"; const uint64_t ino = 42; - const uint64_t generation = 13; struct stat sb; EXPECT_LOOKUP(1, RELPATH).WillRepeatedly(Invoke([=](auto in, auto out) { @@ -53,7 +52,6 @@ TEST_F(Getattr, DISABLED_attr_cache) SET_OUT_HEADER_LEN(out, entry); out->body.entry.attr.mode = S_IFREG | 0644; out->body.entry.nodeid = ino; - out->body.entry.generation = generation; })); EXPECT_CALL(*m_mock, process( ResultOf([](auto in) { @@ -84,7 +82,6 @@ TEST_F(Getattr, attr_cache_timeout) const char FULLPATH[] = "mountpoint/some_file.txt"; const char RELPATH[] = "some_file.txt"; const uint64_t ino = 42; - const uint64_t generation = 13; struct stat sb; /* * The timeout should be longer than the longest plausible time the @@ -92,14 +89,7 @@ TEST_F(Getattr, attr_cache_timeout) */ long timeout_ns = 250'000'000; - EXPECT_LOOKUP(1, RELPATH).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.entry_valid = UINT64_MAX; - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - out->body.entry.generation = generation; - })); + expect_lookup(RELPATH, ino, S_IFREG | 0644, 2); EXPECT_CALL(*m_mock, process( ResultOf([](auto in) { return (in->header.opcode == FUSE_GETATTR && @@ -128,13 +118,7 @@ TEST_F(Getattr, enoent) struct stat sb; const uint64_t ino = 42; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = 0100644; - out->body.entry.nodeid = ino; - })); - + expect_lookup(RELPATH, ino, S_IFREG | 0644, 1); EXPECT_CALL(*m_mock, process( ResultOf([](auto in) { return (in->header.opcode == FUSE_GETATTR && @@ -151,16 +135,9 @@ TEST_F(Getattr, ok) const char FULLPATH[] = "mountpoint/some_file.txt"; const char RELPATH[] = "some_file.txt"; const uint64_t ino = 42; - const uint64_t generation = 13; struct stat sb; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - out->body.entry.generation = generation; - })); + expect_lookup(RELPATH, ino, S_IFREG | 0644, 1); EXPECT_CALL(*m_mock, process( ResultOf([](auto in) { return (in->header.opcode == FUSE_GETATTR && @@ -202,9 +179,6 @@ TEST_F(Getattr, ok) EXPECT_EQ(ino, sb.st_ino); EXPECT_EQ(S_IFREG | 0644, sb.st_mode); - // fuse(4) does not _yet_ support inode generations - //EXPECT_EQ(generation, sb.st_gen); - //st_birthtim and st_flags are not supported by protocol 7.8. They're //only supported as OS-specific extensions to OSX. //EXPECT_EQ(, sb.st_birthtim); diff --git a/tests/sys/fs/fuse/link.cc b/tests/sys/fs/fuse/link.cc index 65acc272629a..84944f42822f 100644 --- a/tests/sys/fs/fuse/link.cc +++ b/tests/sys/fs/fuse/link.cc @@ -37,7 +37,13 @@ extern "C" { using namespace testing; -class Link: public FuseTest {}; +class Link: public FuseTest { +public: +void expect_lookup(const char *relpath, uint64_t ino) +{ + FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, 1); +} +}; TEST_F(Link, emlink) { @@ -48,12 +54,7 @@ TEST_F(Link, emlink) uint64_t dst_ino = 42; EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke(ReturnErrno(ENOENT))); - EXPECT_LOOKUP(1, RELDST).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = dst_ino; - SET_OUT_HEADER_LEN(out, entry); - })); + expect_lookup(RELDST, dst_ino); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { @@ -80,12 +81,7 @@ TEST_F(Link, ok) const uint64_t ino = 42; EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke(ReturnErrno(ENOENT))); - EXPECT_LOOKUP(1, RELDST).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = dst_ino; - SET_OUT_HEADER_LEN(out, entry); - })); + expect_lookup(RELDST, dst_ino); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { diff --git a/tests/sys/fs/fuse/locks.cc b/tests/sys/fs/fuse/locks.cc index f0cc1476a2e6..6a6f8d8a3044 100644 --- a/tests/sys/fs/fuse/locks.cc +++ b/tests/sys/fs/fuse/locks.cc @@ -43,51 +43,10 @@ using namespace testing; /* For testing filesystems without posix locking support */ class Fallback: public FuseTest { public: -const static uint64_t FH = 0xdeadbeef1a7ebabe; - -void expect_getattr(uint64_t ino) -{ - /* Until the attr cache is working, we may send an additional GETATTR */ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_GETATTR && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, attr); - out->body.attr.attr.ino = ino; // Must match nodeid - out->body.attr.attr.mode = S_IFREG | 0644; - out->body.attr.attr_valid = UINT64_MAX; - })); -} void expect_lookup(const char *relpath, uint64_t ino) { - EXPECT_LOOKUP(1, relpath).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - out->body.entry.attr_valid = UINT64_MAX; - })); -} - -void expect_open(uint64_t ino) -{ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_OPEN && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->header.len = sizeof(out->header); - SET_OUT_HEADER_LEN(out, open); - out->body.open.fh = FH; - })); + FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, 1); } }; @@ -120,8 +79,8 @@ TEST_F(GetlkFallback, local) int fd; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); fd = open(FULLPATH, O_RDWR); ASSERT_LE(0, fd) << strerror(errno); @@ -150,8 +109,8 @@ TEST_F(Getlk, DISABLED_no_locks) pid_t pid = 1234; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_GETLK && @@ -197,8 +156,8 @@ TEST_F(Getlk, DISABLED_lock_exists) pid_t pid2 = 1234; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_GETLK && @@ -251,8 +210,8 @@ TEST_F(SetlkFallback, local) int fd; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); fd = open(FULLPATH, O_RDWR); ASSERT_LE(0, fd) << strerror(errno); @@ -278,8 +237,8 @@ TEST_F(Setlk, DISABLED_set) pid_t pid = 1234; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_SETLK && @@ -323,8 +282,8 @@ TEST_F(Setlk, DISABLED_set_eof) pid_t pid = 1234; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_SETLK && @@ -368,8 +327,8 @@ TEST_F(Setlk, DISABLED_eagain) pid_t pid = 1234; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_SETLK && @@ -410,8 +369,8 @@ TEST_F(SetlkwFallback, local) int fd; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); fd = open(FULLPATH, O_RDWR); ASSERT_LE(0, fd) << strerror(errno); @@ -441,8 +400,8 @@ TEST_F(Setlkw, DISABLED_set) pid_t pid = 1234; expect_lookup(RELPATH, ino); - expect_open(ino); - expect_getattr(ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_SETLK && diff --git a/tests/sys/fs/fuse/lookup.cc b/tests/sys/fs/fuse/lookup.cc index 13fe5d370a60..86ab5d7d3087 100644 --- a/tests/sys/fs/fuse/lookup.cc +++ b/tests/sys/fs/fuse/lookup.cc @@ -49,6 +49,7 @@ TEST_F(Lookup, DISABLED_attr_cache) const char FULLPATH[] = "mountpoint/some_file.txt"; const char RELPATH[] = "some_file.txt"; const uint64_t ino = 42; + const uint64_t generation = 13; struct stat sb; EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](auto in, auto out) { @@ -70,6 +71,7 @@ TEST_F(Lookup, DISABLED_attr_cache) out->body.entry.attr.uid = 10; out->body.entry.attr.gid = 11; out->body.entry.attr.rdev = 12; + out->body.entry.generation = generation; })); /* stat(2) issues a VOP_LOOKUP followed by a VOP_GETATTR */ ASSERT_EQ(0, stat(FULLPATH, &sb)) << strerror(errno); @@ -124,18 +126,7 @@ TEST_F(Lookup, attr_cache_timeout) out->body.entry.attr.ino = ino; // Must match nodeid out->body.entry.attr.mode = S_IFREG | 0644; })); - EXPECT_CALL(*m_mock, process( - ResultOf([](auto in) { - return (in->header.opcode == FUSE_GETATTR && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).WillOnce(Invoke([](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, attr); - out->body.attr.attr.ino = ino; // Must match nodeid - out->body.attr.attr.mode = S_IFREG | 0644; - })); + expect_getattr(ino, 0); /* access(2) will issue a VOP_LOOKUP but not a VOP_GETATTR */ ASSERT_EQ(0, access(FULLPATH, F_OK)) << strerror(errno); @@ -246,6 +237,12 @@ TEST_F(Lookup, DISABLED_entry_cache_timeout) ASSERT_EQ(0, access(FULLPATH, F_OK)) << strerror(errno); } +// TODO: export_support +// After upgrading the protocol to 7.10, check that the kernel will only +// attempt to lookup "." and ".." if the filesystem sets FUSE_EXPORT_SUPPORT in +// the init flags. If not, then all lookups for those entries will return +// ESTALE. + TEST_F(Lookup, ok) { const char FULLPATH[] = "mountpoint/some_file.txt"; diff --git a/tests/sys/fs/fuse/mkdir.cc b/tests/sys/fs/fuse/mkdir.cc index 25c07421053a..2066c33eb2a8 100644 --- a/tests/sys/fs/fuse/mkdir.cc +++ b/tests/sys/fs/fuse/mkdir.cc @@ -145,14 +145,7 @@ TEST_F(Mkdir, DISABLED_entry_cache_negative_purge) ASSERT_EQ(0, mkdir(FULLPATH, mode)) << strerror(errno); /* Finally, a subsequent lookup should query the daemon */ - EXPECT_LOOKUP(1, RELPATH).Times(1) - .WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->header.error = 0; - out->body.entry.nodeid = ino; - out->body.entry.attr.mode = S_IFDIR | mode; - SET_OUT_HEADER_LEN(out, entry); - })); + expect_lookup(RELPATH, ino, S_IFDIR | mode, 1); ASSERT_EQ(0, access(FULLPATH, F_OK)) << strerror(errno); } diff --git a/tests/sys/fs/fuse/open.cc b/tests/sys/fs/fuse/open.cc index c3a289c7b327..1b1aa0d899ae 100644 --- a/tests/sys/fs/fuse/open.cc +++ b/tests/sys/fs/fuse/open.cc @@ -48,14 +48,7 @@ void test_ok(int os_flags, int fuse_flags) { uint64_t ino = 42; int fd; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - out->body.entry.attr_valid = UINT64_MAX; - })); - + FuseTest::expect_lookup(RELPATH, ino, S_IFREG | 0644, 1); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_OPEN && @@ -101,13 +94,7 @@ TEST_F(Open, enoent) const char RELPATH[] = "some_file.txt"; uint64_t ino = 42; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - })); - + expect_lookup(RELPATH, ino, S_IFREG | 0644, 1); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_OPEN && @@ -129,13 +116,7 @@ TEST_F(Open, eperm) const char RELPATH[] = "some_file.txt"; uint64_t ino = 42; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - })); - + expect_lookup(RELPATH, ino, S_IFREG | 0644, 1); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_OPEN && diff --git a/tests/sys/fs/fuse/opendir.cc b/tests/sys/fs/fuse/opendir.cc index 2c9524267815..d15e5138654c 100644 --- a/tests/sys/fs/fuse/opendir.cc +++ b/tests/sys/fs/fuse/opendir.cc @@ -42,13 +42,7 @@ class Opendir: public FuseTest { public: void expect_lookup(const char *relpath, uint64_t ino) { - EXPECT_LOOKUP(1, relpath).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFDIR | 0755; - out->body.entry.nodeid = ino; - out->body.entry.attr_valid = UINT64_MAX; - })); + FuseTest::expect_lookup(relpath, ino, S_IFDIR | 0755, 1); } }; diff --git a/tests/sys/fs/fuse/read.cc b/tests/sys/fs/fuse/read.cc index d72f1fedb453..1a6842706452 100644 --- a/tests/sys/fs/fuse/read.cc +++ b/tests/sys/fs/fuse/read.cc @@ -48,72 +48,9 @@ using namespace testing; class Read: public FuseTest { public: -const static uint64_t FH = 0xdeadbeef1a7ebabe; -void expect_getattr(uint64_t ino, uint64_t size) -{ - /* Until the attr cache is working, we may send an additional GETATTR */ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_GETATTR && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, attr); - out->body.attr.attr.ino = ino; // Must match nodeid - out->body.attr.attr.mode = S_IFREG | 0644; - out->body.attr.attr.size = size; - })); - -} - void expect_lookup(const char *relpath, uint64_t ino) { - EXPECT_LOOKUP(1, relpath).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - out->body.entry.attr_valid = UINT64_MAX; - })); -} - -void expect_open(uint64_t ino, uint32_t flags, int times) -{ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_OPEN && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).Times(times) - .WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->header.len = sizeof(out->header); - SET_OUT_HEADER_LEN(out, open); - out->body.open.fh = Read::FH; - out->body.open.open_flags = flags; - })); -} - -void expect_read(uint64_t ino, uint64_t offset, uint64_t isize, uint64_t osize, - const void *contents) -{ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_READ && - in->header.nodeid == ino && - in->body.read.fh == Read::FH && - in->body.read.offset == offset && - in->body.read.size == isize); - }, Eq(true)), - _) - ).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->header.len = sizeof(struct fuse_out_header) + osize; - memmove(out->body.bytes, contents, osize); - })).RetiresOnSaturation(); + FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, 1); } }; diff --git a/tests/sys/fs/fuse/readdir.cc b/tests/sys/fs/fuse/readdir.cc index 3258947103f8..641a2ef19aa9 100644 --- a/tests/sys/fs/fuse/readdir.cc +++ b/tests/sys/fs/fuse/readdir.cc @@ -40,43 +40,10 @@ using namespace testing; using namespace std; class Readdir: public FuseTest { -const static uint64_t FH = 0xdeadbeef1a7ebabe; public: void expect_lookup(const char *relpath, uint64_t ino) { - EXPECT_LOOKUP(1, relpath).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFDIR | 0755; - out->body.entry.nodeid = ino; - out->body.entry.attr_valid = UINT64_MAX; - })); -} - -void expect_opendir(uint64_t ino) -{ - EXPECT_CALL(*m_mock, process( - ResultOf([](auto in) { - return (in->header.opcode == FUSE_STATFS); - }, Eq(true)), - _) - ).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, statfs); - })); - - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_OPENDIR && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->header.len = sizeof(out->header); - SET_OUT_HEADER_LEN(out, open); - out->body.open.fh = FH; - })); + FuseTest::expect_lookup(relpath, ino, S_IFDIR | 0755, 1); } void expect_readdir(uint64_t ino, uint64_t off, vector &ents) diff --git a/tests/sys/fs/fuse/readlink.cc b/tests/sys/fs/fuse/readlink.cc index 8d94cab790fb..ff3490f4e1a5 100644 --- a/tests/sys/fs/fuse/readlink.cc +++ b/tests/sys/fs/fuse/readlink.cc @@ -37,7 +37,13 @@ extern "C" { using namespace testing; -class Readlink: public FuseTest {}; +class Readlink: public FuseTest { +public: +void expect_lookup(const char *relpath, uint64_t ino) +{ + FuseTest::expect_lookup(relpath, ino, S_IFLNK | 0777, 1); +} +}; TEST_F(Readlink, eloop) { @@ -46,12 +52,7 @@ TEST_F(Readlink, eloop) const uint64_t ino = 42; char buf[80]; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFLNK | 0777; - out->body.entry.nodeid = ino; - })); + expect_lookup(RELPATH, ino); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { @@ -73,12 +74,7 @@ TEST_F(Readlink, ok) const uint64_t ino = 42; char buf[80]; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFLNK | 0777; - out->body.entry.nodeid = ino; - })); + expect_lookup(RELPATH, ino); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { diff --git a/tests/sys/fs/fuse/release.cc b/tests/sys/fs/fuse/release.cc index f53ef08e98df..71cf3392a532 100644 --- a/tests/sys/fs/fuse/release.cc +++ b/tests/sys/fs/fuse/release.cc @@ -40,67 +40,10 @@ using namespace testing; class Release: public FuseTest { -const static uint64_t FH = 0xdeadbeef1a7ebabe; - public: -void expect_getattr(uint64_t ino) +void expect_lookup(const char *relpath, uint64_t ino, int times) { - /* Until the attr cache is working, we may send an additional GETATTR */ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_GETATTR && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, attr); - out->body.attr.attr.ino = ino; // Must match nodeid - out->body.attr.attr.mode = S_IFREG | 0644; - })); - -} - -void expect_lookup(const char *relpath, uint64_t ino) -{ - EXPECT_LOOKUP(1, relpath).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - out->body.entry.attr_valid = UINT64_MAX; - })); -} - -void expect_open(uint64_t ino, int times) -{ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_OPEN && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).Times(times) - .WillRepeatedly(Invoke([](auto in, auto out) { - out->header.unique = in->header.unique; - out->header.len = sizeof(out->header); - SET_OUT_HEADER_LEN(out, open); - out->body.open.fh = Release::FH; - })); - -} - -void expect_release(uint64_t ino, int times, ProcessMockerT r) -{ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_RELEASE && - in->header.nodeid == ino && - in->body.release.fh == Release::FH); - }, Eq(true)), - _) - ).Times(times) - .WillRepeatedly(Invoke(r)); + FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, times); } }; @@ -114,10 +57,10 @@ TEST_F(Release, dup) uint64_t ino = 42; int fd, fd2; - expect_lookup(RELPATH, ino); - expect_open(ino, 1); - expect_getattr(ino); - expect_release(ino, 1, ReturnErrno(0)); + expect_lookup(RELPATH, ino, 1); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); + expect_release(ino, 1, 0); fd = open(FULLPATH, O_RDONLY); EXPECT_LE(0, fd) << strerror(errno); @@ -143,10 +86,10 @@ TEST_F(Release, eio) uint64_t ino = 42; int fd; - expect_lookup(RELPATH, ino); - expect_open(ino, 1); - expect_getattr(ino); - expect_release(ino, 1, ReturnErrno(EIO)); + expect_lookup(RELPATH, ino, 1); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); + expect_release(ino, 1, EIO); fd = open(FULLPATH, O_WRONLY); EXPECT_LE(0, fd) << strerror(errno); @@ -166,10 +109,10 @@ TEST_F(Release, multiple_opens) uint64_t ino = 42; int fd, fd2; - expect_lookup(RELPATH, ino); - expect_open(ino, 2); - expect_getattr(ino); - expect_release(ino, 2, ReturnErrno(0)); + expect_lookup(RELPATH, ino, 2); + expect_open(ino, 0, 2); + expect_getattr(ino, 0); + expect_release(ino, 2, 0); fd = open(FULLPATH, O_RDONLY); EXPECT_LE(0, fd) << strerror(errno); @@ -188,10 +131,10 @@ TEST_F(Release, ok) uint64_t ino = 42; int fd; - expect_lookup(RELPATH, ino); - expect_open(ino, 1); - expect_getattr(ino); - expect_release(ino, 1, ReturnErrno(0)); + expect_lookup(RELPATH, ino, 1); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); + expect_release(ino, 1, 0); fd = open(FULLPATH, O_RDONLY); EXPECT_LE(0, fd) << strerror(errno); diff --git a/tests/sys/fs/fuse/releasedir.cc b/tests/sys/fs/fuse/releasedir.cc index c66918a834c6..e2b10dd3e106 100644 --- a/tests/sys/fs/fuse/releasedir.cc +++ b/tests/sys/fs/fuse/releasedir.cc @@ -39,44 +39,10 @@ using namespace testing; class ReleaseDir: public FuseTest { -const static uint64_t FH = 0xdeadbeef1a7ebabe; - public: void expect_lookup(const char *relpath, uint64_t ino) { - EXPECT_LOOKUP(1, relpath).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFDIR | 0755; - out->body.entry.nodeid = ino; - out->body.entry.attr_valid = UINT64_MAX; - })); -} - -void expect_opendir(uint64_t ino) -{ - EXPECT_CALL(*m_mock, process( - ResultOf([](auto in) { - return (in->header.opcode == FUSE_STATFS); - }, Eq(true)), - _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, statfs); - })); - - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_OPENDIR && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->header.len = sizeof(out->header); - SET_OUT_HEADER_LEN(out, open); - out->body.open.fh = FH; - })); + FuseTest::expect_lookup(relpath, ino, S_IFDIR | 0755, 1); } void expect_releasedir(uint64_t ino, ProcessMockerT r) diff --git a/tests/sys/fs/fuse/rename.cc b/tests/sys/fs/fuse/rename.cc index a15a90718742..ed37f3f8ba14 100644 --- a/tests/sys/fs/fuse/rename.cc +++ b/tests/sys/fs/fuse/rename.cc @@ -62,12 +62,7 @@ TEST_F(Rename, einval) const char RELSRC[] = "src"; uint64_t src_ino = 42; - EXPECT_LOOKUP(1, RELSRC).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->body.entry.attr.mode = S_IFDIR | 0755; - out->body.entry.nodeid = src_ino; - SET_OUT_HEADER_LEN(out, entry); - })); + expect_lookup(RELSRC, src_ino, S_IFDIR | 0755, 2); EXPECT_LOOKUP(src_ino, RELDST).WillOnce(Invoke(ReturnErrno(ENOENT))); ASSERT_NE(0, rename(FULLSRC, FULLDST)); @@ -80,7 +75,7 @@ TEST_F(Rename, enoent) const char FULLDST[] = "mountpoint/dst"; const char FULLSRC[] = "mountpoint/src"; const char RELSRC[] = "src"; - // FUSE hardcodes the mountpoint to inocde 1 + // FUSE hardcodes the mountpoint to inode 1 EXPECT_LOOKUP(1, RELSRC).WillOnce(Invoke(ReturnErrno(ENOENT))); @@ -98,7 +93,7 @@ TEST_F(Rename, DISABLED_entry_cache_negative) const char RELDST[] = "dst"; const char FULLSRC[] = "mountpoint/src"; const char RELSRC[] = "src"; - // FUSE hardcodes the mountpoint to inocde 1 + // FUSE hardcodes the mountpoint to inode 1 uint64_t dst_dir_ino = 1; uint64_t ino = 42; /* @@ -108,13 +103,7 @@ TEST_F(Rename, DISABLED_entry_cache_negative) */ struct timespec entry_valid = {.tv_sec = 0, .tv_nsec = 0}; - EXPECT_LOOKUP(1, RELSRC).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - SET_OUT_HEADER_LEN(out, entry); - })); - + expect_lookup(RELSRC, ino, S_IFREG | 0644, 1); /* LOOKUP returns a negative cache entry for dst */ EXPECT_LOOKUP(1, RELDST).WillOnce(ReturnNegativeCache(&entry_valid)); @@ -144,7 +133,7 @@ TEST_F(Rename, DISABLED_entry_cache_negative_purge) const char RELDST[] = "dst"; const char FULLSRC[] = "mountpoint/src"; const char RELSRC[] = "src"; - // FUSE hardcodes the mountpoint to inocde 1 + // FUSE hardcodes the mountpoint to inode 1 uint64_t dst_dir_ino = 1; uint64_t ino = 42; /* @@ -154,13 +143,7 @@ TEST_F(Rename, DISABLED_entry_cache_negative_purge) */ struct timespec entry_valid = {.tv_sec = 0, .tv_nsec = 0}; - EXPECT_LOOKUP(1, RELSRC).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - SET_OUT_HEADER_LEN(out, entry); - })); - + expect_lookup(RELSRC, ino, S_IFREG | 0644, 1); /* LOOKUP returns a negative cache entry for dst */ EXPECT_LOOKUP(1, RELDST).WillOnce(ReturnNegativeCache(&entry_valid)) .RetiresOnSaturation(); @@ -181,14 +164,7 @@ TEST_F(Rename, DISABLED_entry_cache_negative_purge) ASSERT_EQ(0, rename(FULLSRC, FULLDST)) << strerror(errno); /* Finally, a subsequent lookup should query the daemon */ - EXPECT_LOOKUP(1, RELDST).Times(1) - .WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->header.error = 0; - out->body.entry.nodeid = ino; - out->body.entry.attr.mode = S_IFREG | 0644; - SET_OUT_HEADER_LEN(out, entry); - })); + expect_lookup(RELSRC, ino, S_IFREG | 0644, 1); ASSERT_EQ(0, access(FULLDST, F_OK)) << strerror(errno); } @@ -197,18 +173,13 @@ TEST_F(Rename, exdev) { const char FULLB[] = "mountpoint/src"; const char RELB[] = "src"; - // FUSE hardcodes the mountpoint to inocde 1 + // FUSE hardcodes the mountpoint to inode 1 uint64_t b_ino = 42; tmpfd = mkstemp(tmpfile); ASSERT_LE(0, tmpfd) << strerror(errno); - EXPECT_LOOKUP(1, RELB).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = b_ino; - SET_OUT_HEADER_LEN(out, entry); - })); + expect_lookup(RELB, b_ino, S_IFREG | 0644, 2); ASSERT_NE(0, rename(tmpfile, FULLB)); ASSERT_EQ(EXDEV, errno); @@ -223,16 +194,11 @@ TEST_F(Rename, ok) const char RELDST[] = "dst"; const char FULLSRC[] = "mountpoint/src"; const char RELSRC[] = "src"; - // FUSE hardcodes the mountpoint to inocde 1 + // FUSE hardcodes the mountpoint to inode 1 uint64_t dst_dir_ino = 1; uint64_t ino = 42; - EXPECT_LOOKUP(1, RELSRC).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - SET_OUT_HEADER_LEN(out, entry); - })); + expect_lookup(RELSRC, ino, S_IFREG | 0644, 1); EXPECT_LOOKUP(1, RELDST).WillOnce(Invoke(ReturnErrno(ENOENT))); EXPECT_CALL(*m_mock, process( @@ -260,23 +226,12 @@ TEST_F(Rename, overwrite) const char RELSRC[] = "src"; // The inode of the already-existing destination file uint64_t dst_ino = 2; - // FUSE hardcodes the mountpoint to inocde 1 + // FUSE hardcodes the mountpoint to inode 1 uint64_t dst_dir_ino = 1; uint64_t ino = 42; - EXPECT_LOOKUP(1, RELSRC).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - SET_OUT_HEADER_LEN(out, entry); - })); - EXPECT_LOOKUP(1, RELDST).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = dst_ino; - SET_OUT_HEADER_LEN(out, entry); - })); - + expect_lookup(RELSRC, ino, S_IFREG | 0644, 1); + expect_lookup(RELDST, dst_ino, S_IFREG | 0644, 1); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { const char *src = (const char*)in->body.bytes + diff --git a/tests/sys/fs/fuse/rmdir.cc b/tests/sys/fs/fuse/rmdir.cc index 72ea9a7ce15e..6f35c33dfd9c 100644 --- a/tests/sys/fs/fuse/rmdir.cc +++ b/tests/sys/fs/fuse/rmdir.cc @@ -37,7 +37,19 @@ extern "C" { using namespace testing; -class Rmdir: public FuseTest {}; +class Rmdir: public FuseTest { +public: +void expect_lookup(const char *relpath, uint64_t ino) +{ + EXPECT_LOOKUP(1, relpath).WillOnce(Invoke([=](auto in, auto out) { + out->header.unique = in->header.unique; + SET_OUT_HEADER_LEN(out, entry); + out->body.entry.attr.mode = S_IFDIR | 0755; + out->body.entry.nodeid = ino; + out->body.entry.attr.nlink = 2; + })); +} +}; TEST_F(Rmdir, enotempty) { @@ -45,13 +57,7 @@ TEST_F(Rmdir, enotempty) const char RELPATH[] = "some_dir"; uint64_t ino = 42; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFDIR | 0755; - out->body.entry.nodeid = ino; - out->body.entry.attr.nlink = 2; - })); + expect_lookup(RELPATH, ino); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_RMDIR && @@ -71,13 +77,7 @@ TEST_F(Rmdir, ok) const char RELPATH[] = "some_dir"; uint64_t ino = 42; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFDIR | 0755; - out->body.entry.nodeid = ino; - out->body.entry.attr.nlink = 2; - })); + expect_lookup(RELPATH, ino); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_RMDIR && diff --git a/tests/sys/fs/fuse/unlink.cc b/tests/sys/fs/fuse/unlink.cc index f103f545d67d..0389d4c7172b 100644 --- a/tests/sys/fs/fuse/unlink.cc +++ b/tests/sys/fs/fuse/unlink.cc @@ -36,7 +36,13 @@ extern "C" { using namespace testing; -class Unlink: public FuseTest {}; +class Unlink: public FuseTest { +public: +void expect_lookup(const char *relpath, uint64_t ino) +{ + FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, 1); +} +}; TEST_F(Unlink, eperm) { @@ -44,13 +50,7 @@ TEST_F(Unlink, eperm) const char RELPATH[] = "some_file.txt"; uint64_t ino = 42; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - out->body.entry.attr.nlink = 1; - })); + expect_lookup(RELPATH, ino); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_UNLINK && @@ -70,13 +70,7 @@ TEST_F(Unlink, ok) const char RELPATH[] = "some_file.txt"; uint64_t ino = 42; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - out->body.entry.attr.nlink = 1; - })); + expect_lookup(RELPATH, ino); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_UNLINK && diff --git a/tests/sys/fs/fuse/utils.cc b/tests/sys/fs/fuse/utils.cc index 61512b698007..300f2daf8ad3 100644 --- a/tests/sys/fs/fuse/utils.cc +++ b/tests/sys/fs/fuse/utils.cc @@ -38,7 +38,9 @@ #include "mockfs.hh" #include "utils.hh" -class FuseEnv: public ::testing::Environment { +using namespace testing; + +class FuseEnv: public Environment { virtual void SetUp() { const char *mod_name = "fuse"; const char *devnode = "/dev/fuse"; @@ -82,6 +84,146 @@ void FuseTest::SetUp() { } } +void FuseTest::expect_getattr(uint64_t ino, uint64_t size) +{ + /* Until the attr cache is working, we may send an additional GETATTR */ + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + return (in->header.opcode == FUSE_GETATTR && + in->header.nodeid == ino); + }, Eq(true)), + _) + ).WillRepeatedly(Invoke([=](auto in, auto out) { + out->header.unique = in->header.unique; + SET_OUT_HEADER_LEN(out, attr); + out->body.attr.attr.ino = ino; // Must match nodeid + out->body.attr.attr.mode = S_IFREG | 0644; + out->body.attr.attr.size = size; + out->body.attr.attr_valid = UINT64_MAX; + })); +} + +void FuseTest::expect_lookup(const char *relpath, uint64_t ino, mode_t mode, + int times) +{ + EXPECT_LOOKUP(1, relpath) + .Times(times) + .WillRepeatedly(Invoke([=](auto in, auto out) { + out->header.unique = in->header.unique; + SET_OUT_HEADER_LEN(out, entry); + out->body.entry.attr.mode = mode; + out->body.entry.nodeid = ino; + out->body.entry.attr.nlink = 1; + out->body.entry.attr_valid = UINT64_MAX; + })); +} + +void FuseTest::expect_open(uint64_t ino, uint32_t flags, int times) +{ + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + return (in->header.opcode == FUSE_OPEN && + in->header.nodeid == ino); + }, Eq(true)), + _) + ).Times(times) + .WillRepeatedly(Invoke([=](auto in, auto out) { + out->header.unique = in->header.unique; + out->header.len = sizeof(out->header); + SET_OUT_HEADER_LEN(out, open); + out->body.open.fh = FH; + out->body.open.open_flags = flags; + })); +} + +void FuseTest::expect_opendir(uint64_t ino) +{ + EXPECT_CALL(*m_mock, process( + ResultOf([](auto in) { + return (in->header.opcode == FUSE_STATFS); + }, Eq(true)), + _) + ).WillRepeatedly(Invoke([=](auto in, auto out) { + out->header.unique = in->header.unique; + SET_OUT_HEADER_LEN(out, statfs); + })); + + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + return (in->header.opcode == FUSE_OPENDIR && + in->header.nodeid == ino); + }, Eq(true)), + _) + ).WillOnce(Invoke([=](auto in, auto out) { + out->header.unique = in->header.unique; + out->header.len = sizeof(out->header); + SET_OUT_HEADER_LEN(out, open); + out->body.open.fh = FH; + })); +} + +void FuseTest::expect_read(uint64_t ino, uint64_t offset, uint64_t isize, + uint64_t osize, const void *contents) +{ + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + return (in->header.opcode == FUSE_READ && + in->header.nodeid == ino && + in->body.read.fh == FH && + in->body.read.offset == offset && + in->body.read.size == isize); + }, Eq(true)), + _) + ).WillOnce(Invoke([=](auto in, auto out) { + out->header.unique = in->header.unique; + out->header.len = sizeof(struct fuse_out_header) + osize; + memmove(out->body.bytes, contents, osize); + })).RetiresOnSaturation(); +} + +void FuseTest::expect_release(uint64_t ino, int times, int error) +{ + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + return (in->header.opcode == FUSE_RELEASE && + in->header.nodeid == ino && + in->body.release.fh == FH); + }, Eq(true)), + _) + ).Times(times) + .WillRepeatedly(Invoke(ReturnErrno(error))); +} +void FuseTest::expect_write(uint64_t ino, uint64_t offset, uint64_t isize, + uint64_t osize, uint32_t flags, const void *contents) +{ + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + const char *buf = (const char*)in->body.bytes + + sizeof(struct fuse_write_in); + bool pid_ok; + + if (in->body.write.write_flags & FUSE_WRITE_CACHE) + pid_ok = true; + else + pid_ok = (pid_t)in->header.pid == getpid(); + + return (in->header.opcode == FUSE_WRITE && + in->header.nodeid == ino && + in->body.write.fh == FH && + in->body.write.offset == offset && + in->body.write.size == isize && + pid_ok && + in->body.write.write_flags == flags && + 0 == bcmp(buf, contents, isize)); + }, Eq(true)), + _) + ).WillOnce(Invoke([=](auto in, auto out) { + out->header.unique = in->header.unique; + SET_OUT_HEADER_LEN(out, write); + out->body.write.size = osize; + })); +} + static void usage(char* progname) { fprintf(stderr, "Usage: %s [-v]\n\t-v increase verbosity\n", progname); exit(2); @@ -91,8 +233,8 @@ int main(int argc, char **argv) { int ch; FuseEnv *fuse_env = new FuseEnv; - ::testing::InitGoogleTest(&argc, argv); - ::testing::AddGlobalTestEnvironment(fuse_env); + InitGoogleTest(&argc, argv); + AddGlobalTestEnvironment(fuse_env); while ((ch = getopt(argc, argv, "v")) != -1) { switch (ch) { diff --git a/tests/sys/fs/fuse/utils.hh b/tests/sys/fs/fuse/utils.hh index ba0a533e508c..de17d08f5aed 100644 --- a/tests/sys/fs/fuse/utils.hh +++ b/tests/sys/fs/fuse/utils.hh @@ -28,11 +28,21 @@ * SUCH DAMAGE. */ +/* + * TODO: remove FUSE_WRITE_CACHE definition when upgrading to protocol 7.9. + * This bit was actually part of kernel protocol version 7.2, but never + * documented until 7.9 + */ +#ifndef FUSE_WRITE_CACHE +#define FUSE_WRITE_CACHE 1 +#endif + class FuseTest : public ::testing::Test { protected: uint32_t m_maxreadahead; uint32_t m_init_flags; MockFS *m_mock = NULL; + const static uint64_t FH = 0xdeadbeef1a7ebabe; public: int m_maxbcachebuf; @@ -52,4 +62,54 @@ class FuseTest : public ::testing::Test { if (m_mock) delete m_mock; } + + /* + * Create an expectation that FUSE_GETATTR will be called for the given + * inode any number of times. It will respond with a few basic + * attributes, like the given size and the mode S_IFREG | 0644 + */ + void expect_getattr(uint64_t ino, uint64_t size); + + /* + * Create an expectation that FUSE_LOOKUP will be called for the given + * path exactly times times. It will respond with inode ino, mode + * mode, and cache validity forever. + */ + void expect_lookup(const char *relpath, uint64_t ino, mode_t mode, + int times); + + /* + * Create an expectation that FUSE_GETATTR will be called for the given + * inode exactly times times. It will return with open_flags flags and + * file handle FH. + */ + void expect_open(uint64_t ino, uint32_t flags, int times); + + /* + * Create an expectation that FUSE_OPENDIR will be called exactly once + * for inode ino. + */ + void expect_opendir(uint64_t ino); + + /* + * Create an expectation that FUSE_READ will be called exactly once for + * the given inode, at offset offset and with size isize. It will + * return the first osize bytes from contents + */ + void expect_read(uint64_t ino, uint64_t offset, uint64_t isize, + uint64_t osize, const void *contents); + + /* + * Create an expectation that FUSE_RELEASE will be called times times + * for the given inode, returning error error + */ + void expect_release(uint64_t ino, int times, int error); + + /* + * Create an expectation that FUSE_WRITE will be called exactly once + * for the given inode, at offset offset, with write_flags flags, + * size isize and buffer contents. It will return osize + */ + void expect_write(uint64_t ino, uint64_t offset, uint64_t isize, + uint64_t osize, uint32_t flags, const void *contents); }; diff --git a/tests/sys/fs/fuse/write.cc b/tests/sys/fs/fuse/write.cc index 136f05f1c71f..7bdd20f694d9 100644 --- a/tests/sys/fs/fuse/write.cc +++ b/tests/sys/fs/fuse/write.cc @@ -43,87 +43,15 @@ extern "C" { #include "mockfs.hh" #include "utils.hh" -/* - * TODO: remove FUSE_WRITE_CACHE definition when upgrading to protocol 7.9. - * This bit was actually part of kernel protocol version 7.2, but never - * documented until 7.9 - */ -#ifndef FUSE_WRITE_CACHE -#define FUSE_WRITE_CACHE 1 -#endif - using namespace testing; class Write: public FuseTest { public: -const static uint64_t FH = 0xdeadbeef1a7ebabe; -void expect_getattr(uint64_t ino, uint64_t size) -{ - /* Until the attr cache is working, we may send an additional GETATTR */ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_GETATTR && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, attr); - out->body.attr.attr.ino = ino; // Must match nodeid - out->body.attr.attr.mode = S_IFREG | 0644; - out->body.attr.attr.size = size; - out->body.attr.attr_valid = UINT64_MAX; - })); - -} void expect_lookup(const char *relpath, uint64_t ino) { - EXPECT_LOOKUP(1, relpath).WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, entry); - out->body.entry.attr.mode = S_IFREG | 0644; - out->body.entry.nodeid = ino; - out->body.entry.attr_valid = UINT64_MAX; - })); -} - -void expect_open(uint64_t ino, uint32_t flags, int times) -{ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_OPEN && - in->header.nodeid == ino); - }, Eq(true)), - _) - ).Times(times) - .WillRepeatedly(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->header.len = sizeof(out->header); - SET_OUT_HEADER_LEN(out, open); - out->body.open.fh = Write::FH; - out->body.open.open_flags = flags; - })); -} - -void expect_read(uint64_t ino, uint64_t offset, uint64_t size, - const void *contents) -{ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - return (in->header.opcode == FUSE_READ && - in->header.nodeid == ino && - in->body.read.fh == Write::FH && - in->body.read.offset == offset && - in->body.read.size == size); - }, Eq(true)), - _) - ).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->header.len = sizeof(struct fuse_out_header) + size; - memmove(out->body.bytes, contents, size); - })).RetiresOnSaturation(); + FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, 1); } void expect_release(uint64_t ino, ProcessMockerT r) @@ -137,37 +65,6 @@ void expect_release(uint64_t ino, ProcessMockerT r) ).WillRepeatedly(Invoke(r)); } -void expect_write(uint64_t ino, uint64_t offset, uint64_t isize, uint64_t osize, - uint32_t flags, const void *contents) -{ - EXPECT_CALL(*m_mock, process( - ResultOf([=](auto in) { - const char *buf = (const char*)in->body.bytes + - sizeof(struct fuse_write_in); - bool pid_ok; - - if (in->body.write.write_flags & FUSE_WRITE_CACHE) - pid_ok = true; - else - pid_ok = (pid_t)in->header.pid == getpid(); - - return (in->header.opcode == FUSE_WRITE && - in->header.nodeid == ino && - in->body.write.fh == Write::FH && - in->body.write.offset == offset && - in->body.write.size == isize && - pid_ok && - in->body.write.write_flags == flags && - 0 == bcmp(buf, contents, isize)); - }, Eq(true)), - _) - ).WillOnce(Invoke([=](auto in, auto out) { - out->header.unique = in->header.unique; - SET_OUT_HEADER_LEN(out, write); - out->body.write.size = osize; - })); -} - }; class AioWrite: public Write { @@ -337,7 +234,7 @@ TEST_F(Write, DISABLED_direct_io_evicts_cache) expect_lookup(RELPATH, ino); expect_open(ino, 0, 1); expect_getattr(ino, bufsize); - expect_read(ino, 0, bufsize, CONTENTS0); + expect_read(ino, 0, bufsize, bufsize, CONTENTS0); expect_write(ino, 0, bufsize, bufsize, 0, CONTENTS1); fd = open(FULLPATH, O_RDWR); @@ -352,7 +249,7 @@ TEST_F(Write, DISABLED_direct_io_evicts_cache) ASSERT_EQ(bufsize, write(fd, CONTENTS1, bufsize)) << strerror(errno); // Read again. Cache should be bypassed - expect_read(ino, 0, bufsize, CONTENTS1); + expect_read(ino, 0, bufsize, bufsize, CONTENTS1); ASSERT_EQ(0, fcntl(fd, F_SETFL, 0)) << strerror(errno); ASSERT_EQ(0, lseek(fd, 0, SEEK_SET)) << strerror(errno); ASSERT_EQ(bufsize, read(fd, readbuf, bufsize)) << strerror(errno); @@ -459,7 +356,7 @@ TEST_F(Write, DISABLED_mmap) expect_lookup(RELPATH, ino); expect_open(ino, 0, 1); expect_getattr(ino, len); - expect_read(ino, 0, len, zeros); + expect_read(ino, 0, len, len, zeros); /* * Writes from the pager may or may not be associated with the correct * pid, so they must set FUSE_WRITE_CACHE @@ -663,7 +560,7 @@ TEST_F(WriteBack, o_direct) expect_open(ino, 0, 1); expect_getattr(ino, 0); expect_write(ino, 0, bufsize, bufsize, 0, CONTENTS); - expect_read(ino, 0, bufsize, CONTENTS); + expect_read(ino, 0, bufsize, bufsize, CONTENTS); fd = open(FULLPATH, O_RDWR | O_DIRECT); EXPECT_LE(0, fd) << strerror(errno);