Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 15 Mar 2019 16:16:51 +0000 (UTC)
From:      Alan Somers <asomers@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r345188 - projects/fuse2/tests/sys/fs/fuse
Message-ID:  <201903151616.x2FGGp4i022599@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: asomers
Date: Fri Mar 15 16:16:50 2019
New Revision: 345188
URL: https://svnweb.freebsd.org/changeset/base/345188

Log:
  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

Modified:
  projects/fuse2/tests/sys/fs/fuse/flush.cc
  projects/fuse2/tests/sys/fs/fuse/fsync.cc
  projects/fuse2/tests/sys/fs/fuse/locks.cc
  projects/fuse2/tests/sys/fs/fuse/mockfs.cc
  projects/fuse2/tests/sys/fs/fuse/mockfs.hh
  projects/fuse2/tests/sys/fs/fuse/release.cc
  projects/fuse2/tests/sys/fs/fuse/setattr.cc
  projects/fuse2/tests/sys/fs/fuse/utils.cc
  projects/fuse2/tests/sys/fs/fuse/utils.hh

Modified: projects/fuse2/tests/sys/fs/fuse/flush.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fuse/flush.cc	Fri Mar 15 15:52:36 2019	(r345187)
+++ projects/fuse2/tests/sys/fs/fuse/flush.cc	Fri Mar 15 16:16:50 2019	(r345188)
@@ -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,11 +146,58 @@ 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);
 	EXPECT_LE(0, fd) << strerror(errno);
 
 	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 */
 }

Modified: projects/fuse2/tests/sys/fs/fuse/fsync.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fuse/fsync.cc	Fri Mar 15 15:52:36 2019	(r345187)
+++ projects/fuse2/tests/sys/fs/fuse/fsync.cc	Fri Mar 15 16:16:50 2019	(r345188)
@@ -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);

Modified: projects/fuse2/tests/sys/fs/fuse/locks.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fuse/locks.cc	Fri Mar 15 15:52:36 2019	(r345187)
+++ projects/fuse2/tests/sys/fs/fuse/locks.cc	Fri Mar 15 16:16:50 2019	(r345188)
@@ -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);

Modified: projects/fuse2/tests/sys/fs/fuse/mockfs.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fuse/mockfs.cc	Fri Mar 15 15:52:36 2019	(r345187)
+++ projects/fuse2/tests/sys/fs/fuse/mockfs.cc	Fri Mar 15 16:16:50 2019	(r345188)
@@ -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;
@@ -186,6 +189,11 @@ void debug_fuseop(const mockfs_buf_in *in)
 		case FUSE_READDIR:
 			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) {

Modified: projects/fuse2/tests/sys/fs/fuse/mockfs.hh
==============================================================================
--- projects/fuse2/tests/sys/fs/fuse/mockfs.hh	Fri Mar 15 15:52:36 2019	(r345187)
+++ projects/fuse2/tests/sys/fs/fuse/mockfs.hh	Fri Mar 15 16:16:50 2019	(r345188)
@@ -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

Modified: projects/fuse2/tests/sys/fs/fuse/release.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fuse/release.cc	Fri Mar 15 15:52:36 2019	(r345187)
+++ projects/fuse2/tests/sys/fs/fuse/release.cc	Fri Mar 15 16:16:50 2019	(r345188)
@@ -47,8 +47,14 @@ void expect_lookup(const char *relpath, uint64_t ino, 
 }
 };
 
-// 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);
 }

Modified: projects/fuse2/tests/sys/fs/fuse/setattr.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fuse/setattr.cc	Fri Mar 15 15:52:36 2019	(r345187)
+++ projects/fuse2/tests/sys/fs/fuse/setattr.cc	Fri Mar 15 16:16:50 2019	(r345188)
@@ -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){}

Modified: projects/fuse2/tests/sys/fs/fuse/utils.cc
==============================================================================
--- projects/fuse2/tests/sys/fs/fuse/utils.cc	Fri Mar 15 15:52:36 2019	(r345187)
+++ projects/fuse2/tests/sys/fs/fuse/utils.cc	Fri Mar 15 16:16:50 2019	(r345188)
@@ -181,12 +181,14 @@ void FuseTest::expect_read(uint64_t ino, uint64_t offs
 	}))).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)),
 		_)

Modified: projects/fuse2/tests/sys/fs/fuse/utils.hh
==============================================================================
--- projects/fuse2/tests/sys/fs/fuse/utils.hh	Fri Mar 15 15:52:36 2019	(r345187)
+++ projects/fuse2/tests/sys/fs/fuse/utils.hh	Fri Mar 15 16:16:50 2019	(r345188)
@@ -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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201903151616.x2FGGp4i022599>