fuse(4): add some miscellaneous test cases that I had overlooked
* Test that FUSE_FLUSH and FUSE_RELEASE release POSIX file locks * Test that FUSE_SETATTR's attr caching feature works * Fix some minor mistakes in the posix file lock tests Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
4da6e8cef1
commit
9ae9282e95
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/fuse2/; revision=345188
@ -41,12 +41,13 @@ using namespace testing;
|
||||
class Flush: public FuseTest {
|
||||
|
||||
public:
|
||||
void expect_flush(uint64_t ino, int times, ProcessMockerT r)
|
||||
void expect_flush(uint64_t ino, int times, pid_t lo, ProcessMockerT r)
|
||||
{
|
||||
EXPECT_CALL(*m_mock, process(
|
||||
ResultOf([=](auto in) {
|
||||
return (in->header.opcode == FUSE_FLUSH &&
|
||||
in->header.nodeid == ino &&
|
||||
in->body.flush.lock_owner == (uint64_t)lo &&
|
||||
in->body.flush.fh == FH);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
@ -74,7 +75,12 @@ void expect_release()
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: lock_owner stuff
|
||||
class FlushWithLocks: public Flush {
|
||||
virtual void SetUp() {
|
||||
m_init_flags = FUSE_POSIX_LOCKS;
|
||||
Flush::SetUp();
|
||||
}
|
||||
};
|
||||
|
||||
/* If a file descriptor is duplicated, every close causes FLUSH */
|
||||
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236405 */
|
||||
@ -88,7 +94,7 @@ TEST_F(Flush, DISABLED_dup)
|
||||
expect_lookup(RELPATH, ino);
|
||||
expect_open(ino, 0, 1);
|
||||
expect_getattr(ino, 0);
|
||||
expect_flush(ino, 2, ReturnErrno(0));
|
||||
expect_flush(ino, 2, 0, ReturnErrno(0));
|
||||
expect_release();
|
||||
|
||||
fd = open(FULLPATH, O_WRONLY);
|
||||
@ -119,7 +125,7 @@ TEST_F(Flush, DISABLED_eio)
|
||||
expect_lookup(RELPATH, ino);
|
||||
expect_open(ino, 0, 1);
|
||||
expect_getattr(ino, 0);
|
||||
expect_flush(ino, 1, ReturnErrno(EIO));
|
||||
expect_flush(ino, 1, 0, ReturnErrno(EIO));
|
||||
expect_release();
|
||||
|
||||
fd = open(FULLPATH, O_WRONLY);
|
||||
@ -140,7 +146,7 @@ TEST_F(Flush, DISABLED_flush)
|
||||
expect_lookup(RELPATH, ino);
|
||||
expect_open(ino, 0, 1);
|
||||
expect_getattr(ino, 0);
|
||||
expect_flush(ino, 1, ReturnErrno(0));
|
||||
expect_flush(ino, 1, 0, ReturnErrno(0));
|
||||
expect_release();
|
||||
|
||||
fd = open(FULLPATH, O_WRONLY);
|
||||
@ -148,3 +154,50 @@ TEST_F(Flush, DISABLED_flush)
|
||||
|
||||
ASSERT_TRUE(0 == close(fd)) << strerror(errno);
|
||||
}
|
||||
|
||||
/*
|
||||
* When closing a file with a POSIX file lock, flush should release the lock,
|
||||
* _even_if_ it's not the process's last file descriptor for this file.
|
||||
*/
|
||||
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236405 */
|
||||
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=234581 */
|
||||
TEST_F(FlushWithLocks, DISABLED_unlock_on_close)
|
||||
{
|
||||
const char FULLPATH[] = "mountpoint/some_file.txt";
|
||||
const char RELPATH[] = "some_file.txt";
|
||||
uint64_t ino = 42;
|
||||
int fd, fd2;
|
||||
struct flock fl;
|
||||
pid_t pid = getpid();
|
||||
|
||||
expect_lookup(RELPATH, ino);
|
||||
expect_open(ino, 0, 1);
|
||||
expect_getattr(ino, 0);
|
||||
EXPECT_CALL(*m_mock, process(
|
||||
ResultOf([=](auto in) {
|
||||
return (in->header.opcode == FUSE_SETLK &&
|
||||
in->header.nodeid == ino &&
|
||||
in->body.setlk.fh == FH);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) {
|
||||
out->header.unique = in->header.unique;
|
||||
SET_OUT_HEADER_LEN(out, setlk);
|
||||
out->body.setlk.lk = in->body.setlk.lk;
|
||||
})));
|
||||
expect_flush(ino, 1, pid, ReturnErrno(0));
|
||||
|
||||
fd = open(FULLPATH, O_RDWR);
|
||||
ASSERT_LE(0, fd) << strerror(errno);
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
fl.l_pid = pid;
|
||||
fl.l_type = F_RDLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_sysid = 0;
|
||||
ASSERT_NE(-1, fcntl(fd, F_SETLKW, &fl)) << strerror(errno);
|
||||
|
||||
fd2 = dup(fd);
|
||||
ASSERT_EQ(0, close(fd2)) << strerror(errno);
|
||||
/* Deliberately leak fd */
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ TEST_F(Fsync, close)
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).Times(0);
|
||||
expect_release(ino, 1, 0);
|
||||
expect_release(ino, 1, 0, 0);
|
||||
|
||||
fd = open(FULLPATH, O_RDWR);
|
||||
ASSERT_LE(0, fd) << strerror(errno);
|
||||
|
@ -120,7 +120,7 @@ TEST_F(Getlk, DISABLED_no_locks)
|
||||
in->body.getlk.lk.start == 10 &&
|
||||
in->body.getlk.lk.end == 1009 &&
|
||||
in->body.getlk.lk.type == F_RDLCK &&
|
||||
in->body.getlk.lk.pid == 10);
|
||||
in->body.getlk.lk.pid == (uint64_t)pid);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) {
|
||||
@ -153,7 +153,7 @@ TEST_F(Getlk, DISABLED_lock_exists)
|
||||
struct flock fl;
|
||||
int fd;
|
||||
pid_t pid = 1234;
|
||||
pid_t pid2 = 1234;
|
||||
pid_t pid2 = 1235;
|
||||
|
||||
expect_lookup(RELPATH, ino);
|
||||
expect_open(ino, 0, 1);
|
||||
@ -167,7 +167,7 @@ TEST_F(Getlk, DISABLED_lock_exists)
|
||||
in->body.getlk.lk.start == 10 &&
|
||||
in->body.getlk.lk.end == 1009 &&
|
||||
in->body.getlk.lk.type == F_RDLCK &&
|
||||
in->body.getlk.lk.pid == 10);
|
||||
in->body.getlk.lk.pid == (uint64_t)pid);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) {
|
||||
@ -243,19 +243,18 @@ TEST_F(Setlk, DISABLED_set)
|
||||
ResultOf([=](auto in) {
|
||||
return (in->header.opcode == FUSE_SETLK &&
|
||||
in->header.nodeid == ino &&
|
||||
in->body.getlk.fh == FH &&
|
||||
in->body.getlk.owner == (uint32_t)pid &&
|
||||
in->body.getlk.lk.start == 10 &&
|
||||
in->body.getlk.lk.end == 1009 &&
|
||||
in->body.getlk.lk.type == F_RDLCK &&
|
||||
in->body.getlk.lk.pid == 10);
|
||||
in->body.setlk.fh == FH &&
|
||||
in->body.setlk.owner == (uint32_t)pid &&
|
||||
in->body.setlk.lk.start == 10 &&
|
||||
in->body.setlk.lk.end == 1009 &&
|
||||
in->body.setlk.lk.type == F_RDLCK &&
|
||||
in->body.setlk.lk.pid == (uint64_t)pid);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) {
|
||||
out->header.unique = in->header.unique;
|
||||
SET_OUT_HEADER_LEN(out, getlk);
|
||||
out->body.getlk.lk = in->body.getlk.lk;
|
||||
out->body.getlk.lk.type = F_UNLCK;
|
||||
SET_OUT_HEADER_LEN(out, setlk);
|
||||
out->body.setlk.lk = in->body.setlk.lk;
|
||||
})));
|
||||
|
||||
fd = open(FULLPATH, O_RDWR);
|
||||
@ -288,19 +287,18 @@ TEST_F(Setlk, DISABLED_set_eof)
|
||||
ResultOf([=](auto in) {
|
||||
return (in->header.opcode == FUSE_SETLK &&
|
||||
in->header.nodeid == ino &&
|
||||
in->body.getlk.fh == FH &&
|
||||
in->body.getlk.owner == (uint32_t)pid &&
|
||||
in->body.getlk.lk.start == 10 &&
|
||||
in->body.getlk.lk.end == OFFSET_MAX &&
|
||||
in->body.getlk.lk.type == F_RDLCK &&
|
||||
in->body.getlk.lk.pid == 10);
|
||||
in->body.setlk.fh == FH &&
|
||||
in->body.setlk.owner == (uint32_t)pid &&
|
||||
in->body.setlk.lk.start == 10 &&
|
||||
in->body.setlk.lk.end == OFFSET_MAX &&
|
||||
in->body.setlk.lk.type == F_RDLCK &&
|
||||
in->body.setlk.lk.pid == (uint64_t)pid);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) {
|
||||
out->header.unique = in->header.unique;
|
||||
SET_OUT_HEADER_LEN(out, getlk);
|
||||
out->body.getlk.lk = in->body.getlk.lk;
|
||||
out->body.getlk.lk.type = F_UNLCK;
|
||||
SET_OUT_HEADER_LEN(out, setlk);
|
||||
out->body.setlk.lk = in->body.setlk.lk;
|
||||
})));
|
||||
|
||||
fd = open(FULLPATH, O_RDWR);
|
||||
@ -333,12 +331,12 @@ TEST_F(Setlk, DISABLED_eagain)
|
||||
ResultOf([=](auto in) {
|
||||
return (in->header.opcode == FUSE_SETLK &&
|
||||
in->header.nodeid == ino &&
|
||||
in->body.getlk.fh == FH &&
|
||||
in->body.getlk.owner == (uint32_t)pid &&
|
||||
in->body.getlk.lk.start == 10 &&
|
||||
in->body.getlk.lk.end == 1009 &&
|
||||
in->body.getlk.lk.type == F_RDLCK &&
|
||||
in->body.getlk.lk.pid == 10);
|
||||
in->body.setlk.fh == FH &&
|
||||
in->body.setlk.owner == (uint32_t)pid &&
|
||||
in->body.setlk.lk.start == 10 &&
|
||||
in->body.setlk.lk.end == 1009 &&
|
||||
in->body.setlk.lk.type == F_RDLCK &&
|
||||
in->body.setlk.lk.pid == (uint64_t)pid);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).WillOnce(Invoke(ReturnErrno(EAGAIN)));
|
||||
@ -406,19 +404,18 @@ TEST_F(Setlkw, DISABLED_set)
|
||||
ResultOf([=](auto in) {
|
||||
return (in->header.opcode == FUSE_SETLK &&
|
||||
in->header.nodeid == ino &&
|
||||
in->body.getlk.fh == FH &&
|
||||
in->body.getlk.owner == (uint32_t)pid &&
|
||||
in->body.getlk.lk.start == 10 &&
|
||||
in->body.getlk.lk.end == 1009 &&
|
||||
in->body.getlk.lk.type == F_RDLCK &&
|
||||
in->body.getlk.lk.pid == 10);
|
||||
in->body.setlkw.fh == FH &&
|
||||
in->body.setlkw.owner == (uint32_t)pid &&
|
||||
in->body.setlkw.lk.start == 10 &&
|
||||
in->body.setlkw.lk.end == 1009 &&
|
||||
in->body.setlkw.lk.type == F_RDLCK &&
|
||||
in->body.setlkw.lk.pid == (uint64_t)pid);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) {
|
||||
out->header.unique = in->header.unique;
|
||||
SET_OUT_HEADER_LEN(out, getlk);
|
||||
out->body.getlk.lk = in->body.getlk.lk;
|
||||
out->body.getlk.lk.type = F_UNLCK;
|
||||
SET_OUT_HEADER_LEN(out, setlkw);
|
||||
out->body.setlkw.lk = in->body.setlkw.lk;
|
||||
})));
|
||||
|
||||
fd = open(FULLPATH, O_RDWR);
|
||||
|
@ -159,6 +159,9 @@ void debug_fuseop(const mockfs_buf_in *in)
|
||||
in->header.unique, in->header.len);
|
||||
}
|
||||
switch (in->header.opcode) {
|
||||
case FUSE_FLUSH:
|
||||
printf(" lock_owner=%lu", in->body.flush.lock_owner);
|
||||
break;
|
||||
case FUSE_FORGET:
|
||||
printf(" nlookup=%lu", in->body.forget.nlookup);
|
||||
break;
|
||||
@ -187,6 +190,11 @@ void debug_fuseop(const mockfs_buf_in *in)
|
||||
printf(" offset=%lu size=%u", in->body.readdir.offset,
|
||||
in->body.readdir.size);
|
||||
break;
|
||||
case FUSE_RELEASE:
|
||||
printf(" flags=%#x lock_owner=%lu",
|
||||
in->body.release.flags,
|
||||
in->body.release.lock_owner);
|
||||
break;
|
||||
case FUSE_SETATTR:
|
||||
if (verbosity <= 1) {
|
||||
printf(" valid=%#x", in->body.setattr.valid);
|
||||
|
@ -104,6 +104,7 @@ union fuse_payloads_in {
|
||||
fuse_setattr_in setattr;
|
||||
fuse_setxattr_in setxattr;
|
||||
fuse_lk_in setlk;
|
||||
fuse_lk_in setlkw;
|
||||
char unlink[0];
|
||||
fuse_write_in write;
|
||||
};
|
||||
@ -125,6 +126,7 @@ union fuse_payloads_out {
|
||||
fuse_listxattr_out listxattr;
|
||||
fuse_open_out open;
|
||||
fuse_lk_out setlk;
|
||||
fuse_lk_out setlkw;
|
||||
fuse_statfs_out statfs;
|
||||
/*
|
||||
* The protocol places no limits on the length of the string. This is
|
||||
|
@ -47,7 +47,13 @@ void expect_lookup(const char *relpath, uint64_t ino, int times)
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: lock owner stuff
|
||||
class ReleaseWithLocks: public Release {
|
||||
virtual void SetUp() {
|
||||
m_init_flags = FUSE_POSIX_LOCKS;
|
||||
Release::SetUp();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* If a file descriptor is duplicated, only the last close causes RELEASE */
|
||||
TEST_F(Release, dup)
|
||||
@ -60,7 +66,7 @@ TEST_F(Release, dup)
|
||||
expect_lookup(RELPATH, ino, 1);
|
||||
expect_open(ino, 0, 1);
|
||||
expect_getattr(ino, 0);
|
||||
expect_release(ino, 1, 0);
|
||||
expect_release(ino, 1, 0, 0);
|
||||
|
||||
fd = open(FULLPATH, O_RDONLY);
|
||||
EXPECT_LE(0, fd) << strerror(errno);
|
||||
@ -89,7 +95,7 @@ TEST_F(Release, eio)
|
||||
expect_lookup(RELPATH, ino, 1);
|
||||
expect_open(ino, 0, 1);
|
||||
expect_getattr(ino, 0);
|
||||
expect_release(ino, 1, EIO);
|
||||
expect_release(ino, 1, 0, EIO);
|
||||
|
||||
fd = open(FULLPATH, O_WRONLY);
|
||||
EXPECT_LE(0, fd) << strerror(errno);
|
||||
@ -112,7 +118,7 @@ TEST_F(Release, multiple_opens)
|
||||
expect_lookup(RELPATH, ino, 2);
|
||||
expect_open(ino, 0, 2);
|
||||
expect_getattr(ino, 0);
|
||||
expect_release(ino, 2, 0);
|
||||
expect_release(ino, 2, 0, 0);
|
||||
|
||||
fd = open(FULLPATH, O_RDONLY);
|
||||
EXPECT_LE(0, fd) << strerror(errno);
|
||||
@ -134,10 +140,51 @@ TEST_F(Release, ok)
|
||||
expect_lookup(RELPATH, ino, 1);
|
||||
expect_open(ino, 0, 1);
|
||||
expect_getattr(ino, 0);
|
||||
expect_release(ino, 1, 0);
|
||||
expect_release(ino, 1, 0, 0);
|
||||
|
||||
fd = open(FULLPATH, O_RDONLY);
|
||||
EXPECT_LE(0, fd) << strerror(errno);
|
||||
|
||||
ASSERT_EQ(0, close(fd)) << strerror(errno);
|
||||
}
|
||||
|
||||
/* When closing a file with a POSIX file lock, release should release the lock*/
|
||||
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=234581 */
|
||||
TEST_F(ReleaseWithLocks, DISABLED_unlock_on_close)
|
||||
{
|
||||
const char FULLPATH[] = "mountpoint/some_file.txt";
|
||||
const char RELPATH[] = "some_file.txt";
|
||||
uint64_t ino = 42;
|
||||
int fd;
|
||||
struct flock fl;
|
||||
pid_t pid = getpid();
|
||||
|
||||
expect_lookup(RELPATH, ino, 1);
|
||||
expect_open(ino, 0, 1);
|
||||
expect_getattr(ino, 0);
|
||||
EXPECT_CALL(*m_mock, process(
|
||||
ResultOf([=](auto in) {
|
||||
return (in->header.opcode == FUSE_SETLK &&
|
||||
in->header.nodeid == ino &&
|
||||
in->body.setlk.fh == FH);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) {
|
||||
out->header.unique = in->header.unique;
|
||||
SET_OUT_HEADER_LEN(out, setlk);
|
||||
out->body.setlk.lk = in->body.setlk.lk;
|
||||
})));
|
||||
expect_release(ino, 1, (uint64_t)pid, 0);
|
||||
|
||||
fd = open(FULLPATH, O_RDWR);
|
||||
ASSERT_LE(0, fd) << strerror(errno);
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
fl.l_pid = pid;
|
||||
fl.l_type = F_RDLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_sysid = 0;
|
||||
ASSERT_NE(-1, fcntl(fd, F_SETLKW, &fl)) << strerror(errno);
|
||||
|
||||
ASSERT_EQ(0, close(fd)) << strerror(errno);
|
||||
}
|
||||
|
@ -42,6 +42,55 @@ using namespace testing;
|
||||
class Setattr : public FuseTest {};
|
||||
|
||||
|
||||
/*
|
||||
* If setattr returns a non-zero cache timeout, then subsequent VOP_GETATTRs
|
||||
* should use the cached attributes, rather than query the daemon
|
||||
*/
|
||||
/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=235775 */
|
||||
TEST_F(Setattr, DISABLED_attr_cache)
|
||||
{
|
||||
const char FULLPATH[] = "mountpoint/some_file.txt";
|
||||
const char RELPATH[] = "some_file.txt";
|
||||
const uint64_t ino = 42;
|
||||
struct stat sb;
|
||||
const mode_t newmode = 0644;
|
||||
|
||||
EXPECT_LOOKUP(1, RELPATH)
|
||||
.WillRepeatedly(Invoke(ReturnImmediate([=](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_CALL(*m_mock, process(
|
||||
ResultOf([](auto in) {
|
||||
/* In protocol 7.23, ctime will be changed too */
|
||||
return (in->header.opcode == FUSE_SETATTR &&
|
||||
in->header.nodeid == ino);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).WillOnce(Invoke(ReturnImmediate([](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 | newmode;
|
||||
})));
|
||||
EXPECT_CALL(*m_mock, process(
|
||||
ResultOf([](auto in) {
|
||||
return (in->header.opcode == FUSE_GETATTR);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
).Times(0);
|
||||
|
||||
/* Set an attribute with SETATTR */
|
||||
ASSERT_EQ(0, chmod(FULLPATH, newmode)) << strerror(errno);
|
||||
|
||||
/* The stat(2) should use cached attributes */
|
||||
ASSERT_EQ(0, stat(FULLPATH, &sb));
|
||||
EXPECT_EQ(S_IFREG | newmode, sb.st_mode);
|
||||
}
|
||||
|
||||
/* Change the mode of a file */
|
||||
TEST_F(Setattr, chmod)
|
||||
{
|
||||
@ -305,7 +354,8 @@ TEST_F(Setattr, truncate) {
|
||||
const uint64_t oldsize = 100'000'000;
|
||||
const uint64_t newsize = 20'000'000;
|
||||
|
||||
EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) {
|
||||
EXPECT_LOOKUP(1, RELPATH)
|
||||
.WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) {
|
||||
out->header.unique = in->header.unique;
|
||||
SET_OUT_HEADER_LEN(out, entry);
|
||||
out->body.entry.attr.mode = S_IFREG | 0644;
|
||||
@ -347,7 +397,8 @@ TEST_F(Setattr, utimensat) {
|
||||
{.tv_sec = 7, .tv_nsec = 8},
|
||||
};
|
||||
|
||||
EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) {
|
||||
EXPECT_LOOKUP(1, RELPATH)
|
||||
.WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) {
|
||||
out->header.unique = in->header.unique;
|
||||
SET_OUT_HEADER_LEN(out, entry);
|
||||
out->body.entry.attr.mode = S_IFREG | 0644;
|
||||
@ -423,7 +474,8 @@ TEST_F(Setattr, utimensat_mtime_only) {
|
||||
{.tv_sec = 7, .tv_nsec = 8},
|
||||
};
|
||||
|
||||
EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) {
|
||||
EXPECT_LOOKUP(1, RELPATH)
|
||||
.WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) {
|
||||
out->header.unique = in->header.unique;
|
||||
SET_OUT_HEADER_LEN(out, entry);
|
||||
out->body.entry.attr.mode = S_IFREG | 0644;
|
||||
@ -481,9 +533,3 @@ TEST_F(Setattr, utimensat_mtime_only) {
|
||||
EXPECT_EQ(0, utimensat(AT_FDCWD, FULLPATH, &newtimes[0], 0))
|
||||
<< strerror(errno);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writethrough cache: newly changed attributes should be automatically cached,
|
||||
* if the filesystem allows it
|
||||
*/
|
||||
//TODO TEST_F(Setattr, writethrough_cache){}
|
||||
|
@ -181,12 +181,14 @@ void FuseTest::expect_read(uint64_t ino, uint64_t offset, uint64_t isize,
|
||||
}))).RetiresOnSaturation();
|
||||
}
|
||||
|
||||
void FuseTest::expect_release(uint64_t ino, int times, int error)
|
||||
void FuseTest::expect_release(uint64_t ino, int times, uint64_t lock_owner,
|
||||
int error)
|
||||
{
|
||||
EXPECT_CALL(*m_mock, process(
|
||||
ResultOf([=](auto in) {
|
||||
return (in->header.opcode == FUSE_RELEASE &&
|
||||
in->header.nodeid == ino &&
|
||||
in->body.release.lock_owner == lock_owner &&
|
||||
in->body.release.fh == FH);
|
||||
}, Eq(true)),
|
||||
_)
|
||||
|
@ -103,7 +103,8 @@ class FuseTest : public ::testing::Test {
|
||||
* 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);
|
||||
void expect_release(uint64_t ino, int times, uint64_t lock_owner,
|
||||
int error);
|
||||
|
||||
/*
|
||||
* Create an expectation that FUSE_WRITE will be called exactly once
|
||||
|
Loading…
Reference in New Issue
Block a user