From 0e6120f53f1902247fd1f293c1f593f3e4393109 Mon Sep 17 00:00:00 2001 From: asomers Date: Thu, 14 Mar 2019 17:20:24 +0000 Subject: [PATCH] fuse(4): add tests for FUSE_INTERRUPT This required changing the way that all operations are mocked. Previously MockFS::process had one input argument and one output argument. Now, it returns a vector of zero or more responses. This allows tests to simulate conditions where the filesystem daemon has a queue depth > 1. PR: 236530 Sponsored by: The FreeBSD Foundation --- tests/sys/fs/fuse/Makefile | 9 + tests/sys/fs/fuse/create.cc | 40 ++-- tests/sys/fs/fuse/fsync.cc | 8 +- tests/sys/fs/fuse/getattr.cc | 16 +- tests/sys/fs/fuse/interrupt.cc | 312 ++++++++++++++++++++++++++++++++ tests/sys/fs/fuse/link.cc | 4 +- tests/sys/fs/fuse/locks.cc | 20 +- tests/sys/fs/fuse/lookup.cc | 34 ++-- tests/sys/fs/fuse/mkdir.cc | 12 +- tests/sys/fs/fuse/mknod.cc | 4 +- tests/sys/fs/fuse/mockfs.cc | 74 ++++---- tests/sys/fs/fuse/mockfs.hh | 30 ++- tests/sys/fs/fuse/open.cc | 8 +- tests/sys/fs/fuse/opendir.cc | 12 +- tests/sys/fs/fuse/read.cc | 8 +- tests/sys/fs/fuse/readdir.cc | 8 +- tests/sys/fs/fuse/readlink.cc | 4 +- tests/sys/fs/fuse/releasedir.cc | 4 +- tests/sys/fs/fuse/rmdir.cc | 5 +- tests/sys/fs/fuse/setattr.cc | 89 ++++----- tests/sys/fs/fuse/statfs.cc | 4 +- tests/sys/fs/fuse/symlink.cc | 4 +- tests/sys/fs/fuse/utils.cc | 28 +-- tests/sys/fs/fuse/write.cc | 8 +- 24 files changed, 551 insertions(+), 194 deletions(-) create mode 100644 tests/sys/fs/fuse/interrupt.cc diff --git a/tests/sys/fs/fuse/Makefile b/tests/sys/fs/fuse/Makefile index 51ae166b227..05bdff6ecd1 100644 --- a/tests/sys/fs/fuse/Makefile +++ b/tests/sys/fs/fuse/Makefile @@ -4,12 +4,16 @@ PACKAGE= tests TESTSDIR= ${TESTSBASE}/sys/fs/fuse +# We could simply link all of these files into a single executable. But since +# Kyua treats googletest programs as plain tests, it's better to separate them +# out, so we get more granular reporting. ATF_TESTS_CXX+= access ATF_TESTS_CXX+= create ATF_TESTS_CXX+= flush ATF_TESTS_CXX+= fsync ATF_TESTS_CXX+= fsyncdir ATF_TESTS_CXX+= getattr +ATF_TESTS_CXX+= interrupt ATF_TESTS_CXX+= link ATF_TESTS_CXX+= locks ATF_TESTS_CXX+= lookup @@ -60,6 +64,11 @@ SRCS.getattr+= getmntopts.c SRCS.getattr+= mockfs.cc SRCS.getattr+= utils.cc +SRCS.interrupt+= interrupt.cc +SRCS.interrupt+= getmntopts.c +SRCS.interrupt+= mockfs.cc +SRCS.interrupt+= utils.cc + SRCS.link+= getmntopts.c SRCS.link+= link.cc SRCS.link+= mockfs.cc diff --git a/tests/sys/fs/fuse/create.cc b/tests/sys/fs/fuse/create.cc index 0d02a4701e0..df8b118f293 100644 --- a/tests/sys/fs/fuse/create.cc +++ b/tests/sys/fs/fuse/create.cc @@ -62,14 +62,14 @@ TEST_F(Create, DISABLED_attr_cache) (0 == strcmp(RELPATH, name))); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, create); out->body.create.entry.attr.mode = S_IFREG | mode; out->body.create.entry.nodeid = ino; out->body.create.entry.entry_valid = UINT64_MAX; out->body.create.entry.attr_valid = UINT64_MAX; - })); + }))); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { @@ -145,14 +145,14 @@ TEST_F(Create, DISABLED_Enosys) (0 == strcmp(RELPATH, name))); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, create); out->body.create.entry.attr.mode = S_IFREG | mode; out->body.create.entry.nodeid = ino; out->body.create.entry.entry_valid = UINT64_MAX; out->body.create.entry.attr_valid = UINT64_MAX; - })); + }))); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { @@ -160,11 +160,11 @@ TEST_F(Create, DISABLED_Enosys) in->header.nodeid == ino); }, Eq(true)), _) - ).WillOnce(Invoke([](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([](auto in, auto out) { out->header.unique = in->header.unique; out->header.len = sizeof(out->header); SET_OUT_HEADER_LEN(out, open); - })); + }))); /* Until the attr cache is working, we may send an additional GETATTR */ EXPECT_CALL(*m_mock, process( @@ -173,12 +173,12 @@ TEST_F(Create, DISABLED_Enosys) in->header.nodeid == ino); }, Eq(true)), _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { + ).WillRepeatedly(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 | 0644; - })); + }))); fd = open(FULLPATH, O_CREAT | O_EXCL, mode); EXPECT_LE(0, fd) << strerror(errno); @@ -214,14 +214,14 @@ TEST_F(Create, DISABLED_entry_cache_negative) (0 == strcmp(RELPATH, name))); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, create); out->body.create.entry.attr.mode = S_IFREG | mode; out->body.create.entry.nodeid = ino; out->body.create.entry.entry_valid = UINT64_MAX; out->body.create.entry.attr_valid = UINT64_MAX; - })); + }))); /* Until the attr cache is working, we may send an additional GETATTR */ EXPECT_CALL(*m_mock, process( @@ -230,12 +230,12 @@ TEST_F(Create, DISABLED_entry_cache_negative) in->header.nodeid == ino); }, Eq(true)), _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { + ).WillRepeatedly(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 | 0644; - })); + }))); fd = open(FULLPATH, O_CREAT | O_EXCL, mode); ASSERT_LE(0, fd) << strerror(errno); @@ -269,13 +269,13 @@ TEST_F(Create, DISABLED_entry_cache_negative_purge) (0 == strcmp(RELPATH, name))); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, create); out->body.create.entry.attr.mode = S_IFREG | mode; out->body.create.entry.nodeid = ino; out->body.create.entry.attr_valid = UINT64_MAX; - })); + }))); /* Until the attr cache is working, we may send an additional GETATTR */ EXPECT_CALL(*m_mock, process( @@ -284,12 +284,12 @@ TEST_F(Create, DISABLED_entry_cache_negative_purge) in->header.nodeid == ino); }, Eq(true)), _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { + ).WillRepeatedly(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 | 0644; - })); + }))); fd = open(FULLPATH, O_CREAT | O_EXCL, mode); ASSERT_LE(0, fd) << strerror(errno); @@ -344,14 +344,14 @@ TEST_F(Create, ok) (0 == strcmp(RELPATH, name))); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, create); out->body.create.entry.attr.mode = S_IFREG | mode; out->body.create.entry.nodeid = ino; out->body.create.entry.entry_valid = UINT64_MAX; out->body.create.entry.attr_valid = UINT64_MAX; - })); + }))); /* Until the attr cache is working, we may send an additional GETATTR */ EXPECT_CALL(*m_mock, process( @@ -360,12 +360,12 @@ TEST_F(Create, ok) in->header.nodeid == ino); }, Eq(true)), _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { + ).WillRepeatedly(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 | 0644; - })); + }))); fd = open(FULLPATH, O_CREAT | O_EXCL, mode); EXPECT_LE(0, fd) << strerror(errno); diff --git a/tests/sys/fs/fuse/fsync.cc b/tests/sys/fs/fuse/fsync.cc index 01b568acb52..c92f1993934 100644 --- a/tests/sys/fs/fuse/fsync.cc +++ b/tests/sys/fs/fuse/fsync.cc @@ -132,11 +132,11 @@ TEST_F(Fsync, close) return (in->header.opcode == FUSE_SETATTR); }, Eq(true)), _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { + ).WillRepeatedly(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 - })); + }))); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { return (in->header.opcode == FUSE_FSYNC); @@ -244,12 +244,12 @@ TEST_F(Fsync, DISABLED_fsync_metadata_only) return (in->header.opcode == FUSE_SETATTR); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).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 | mode; - })); + }))); expect_fsync(ino, 0, 0); diff --git a/tests/sys/fs/fuse/getattr.cc b/tests/sys/fs/fuse/getattr.cc index c107c74bc87..bee203e515f 100644 --- a/tests/sys/fs/fuse/getattr.cc +++ b/tests/sys/fs/fuse/getattr.cc @@ -47,25 +47,25 @@ TEST_F(Getattr, DISABLED_attr_cache) const uint64_t ino = 42; struct stat sb; - EXPECT_LOOKUP(1, RELPATH).WillRepeatedly(Invoke([=](auto in, auto out) { + 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) { return (in->header.opcode == FUSE_GETATTR && in->header.nodeid == ino); }, Eq(true)), _) - ).WillOnce(Invoke([](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, attr); out->body.attr.attr_valid = UINT64_MAX; out->body.attr.attr.ino = ino; // Must match nodeid out->body.attr.attr.mode = S_IFREG | 0644; - })); + }))); EXPECT_EQ(0, stat(FULLPATH, &sb)); /* The second stat(2) should use cached attributes */ EXPECT_EQ(0, stat(FULLPATH, &sb)); @@ -97,14 +97,14 @@ TEST_F(Getattr, attr_cache_timeout) }, Eq(true)), _) ).Times(2) - .WillRepeatedly(Invoke([=](auto in, auto out) { + .WillRepeatedly(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, attr); out->body.attr.attr_valid_nsec = timeout_ns; out->body.attr.attr_valid = UINT64_MAX; out->body.attr.attr.ino = ino; // Must match nodeid out->body.attr.attr.mode = S_IFREG | 0644; - })); + }))); EXPECT_EQ(0, stat(FULLPATH, &sb)); usleep(2 * timeout_ns / 1000); /* Timeout has expire. stat(2) should requery the daemon */ @@ -144,7 +144,7 @@ TEST_F(Getattr, ok) in->header.nodeid == ino); }, Eq(true)), _) - ).WillOnce(Invoke([](auto in, auto out) { + ).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 @@ -161,7 +161,7 @@ TEST_F(Getattr, ok) out->body.attr.attr.uid = 10; out->body.attr.attr.gid = 11; out->body.attr.attr.rdev = 12; - })); + }))); ASSERT_EQ(0, stat(FULLPATH, &sb)) << strerror(errno); EXPECT_EQ(1, sb.st_size); diff --git a/tests/sys/fs/fuse/interrupt.cc b/tests/sys/fs/fuse/interrupt.cc new file mode 100644 index 00000000000..3c4767845e7 --- /dev/null +++ b/tests/sys/fs/fuse/interrupt.cc @@ -0,0 +1,312 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2019 The FreeBSD Foundation + * + * This software was developed by BFF Storage Systems, LLC under sponsorship + * from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +extern "C" { +#include +#include +#include +} + +#include "mockfs.hh" +#include "utils.hh" + +using namespace testing; + +/* Don't do anything; all we care about is that the syscall gets interrupted */ +void sigusr2_handler(int __unused sig) { + if (verbosity > 1) + printf("Signaled!\n"); +} + +void* killer(void* target) { + /* + * Sleep for awhile so we can be mostly confident that the main thread + * is already blocked in write(2) + */ + usleep(250'000); + if (verbosity > 1) + printf("Signalling!\n"); + pthread_kill(*(pthread_t*)target, SIGUSR2); + + return(NULL); +} + +class Interrupt: public FuseTest { +public: +pthread_t m_child; + +Interrupt(): m_child(NULL) {}; + +void expect_lookup(const char *relpath, uint64_t ino) +{ + FuseTest::expect_lookup(relpath, ino, S_IFREG | 0644, 1); +} + +/* + * Expect a FUSE_WRITE but don't reply. Instead, just record the unique value + * to the provided pointer + */ +void expect_write(uint64_t ino, uint64_t *write_unique) +{ + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + return (in->header.opcode == FUSE_WRITE && + in->header.nodeid == ino); + }, Eq(true)), + _) + ).WillOnce(Invoke([=](auto in, auto &out __unused) { + *write_unique = in->header.unique; + })); +} + +void setup_interruptor(pthread_t self) +{ + ASSERT_EQ(0, signal(SIGUSR2, sigusr2_handler)) << strerror(errno); + ASSERT_EQ(0, pthread_create(&m_child, NULL, killer, (void*)self)) + << strerror(errno); +} + +void TearDown() { + if (m_child != NULL) { + pthread_join(m_child, NULL); + } + + FuseTest::TearDown(); +} +}; + +/* + * An interrupt operation that gets received after the original command is + * complete should generate an EAGAIN response. + */ +/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ +TEST_F(Interrupt, DISABLED_already_complete) +{ + const char FULLPATH[] = "mountpoint/some_file.txt"; + const char RELPATH[] = "some_file.txt"; + const char *CONTENTS = "abcdefgh"; + uint64_t ino = 42; + int fd; + ssize_t bufsize = strlen(CONTENTS); + pthread_t self; + uint64_t write_unique = 0; + + self = pthread_self(); + + expect_lookup(RELPATH, ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); + expect_write(ino, &write_unique); + EXPECT_CALL(*m_mock, process( + ResultOf([&](auto in) { + return (in->header.opcode == FUSE_INTERRUPT && + in->body.interrupt.unique == write_unique); + }, Eq(true)), + _) + ).WillOnce(Invoke([&](auto in, auto &out) { + // First complete the write request + auto out0 = new mockfs_buf_out; + out0->header.unique = write_unique; + SET_OUT_HEADER_LEN(out0, write); + out0->body.write.size = bufsize; + out.push_back(out0); + + // Then, respond EAGAIN to the interrupt request + auto out1 = new mockfs_buf_out; + out1->header.unique = in->header.unique; + out1->header.error = -EAGAIN; + out1->header.len = sizeof(out1->header); + out.push_back(out1); + })); + + fd = open(FULLPATH, O_WRONLY); + ASSERT_LE(0, fd) << strerror(errno); + + setup_interruptor(self); + ASSERT_EQ(bufsize, write(fd, CONTENTS, bufsize)) << strerror(errno); + + /* Deliberately leak fd. close(2) will be tested in release.cc */ +} + +/* + * A FUSE filesystem is legally allowed to ignore INTERRUPT operations, and + * complete the original operation whenever it damn well pleases. + */ +/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ +TEST_F(Interrupt, DISABLED_ignore) +{ + const char FULLPATH[] = "mountpoint/some_file.txt"; + const char RELPATH[] = "some_file.txt"; + const char *CONTENTS = "abcdefgh"; + uint64_t ino = 42; + int fd; + ssize_t bufsize = strlen(CONTENTS); + pthread_t self; + uint64_t write_unique; + + self = pthread_self(); + + expect_lookup(RELPATH, ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); + expect_write(ino, &write_unique); + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + return (in->header.opcode == FUSE_INTERRUPT && + in->body.interrupt.unique == write_unique); + }, Eq(true)), + _) + ).WillOnce(Invoke([&](auto in __unused, auto &out) { + // Ignore FUSE_INTERRUPT; respond to the FUSE_WRITE + auto out0 = new mockfs_buf_out; + out0->header.unique = write_unique; + SET_OUT_HEADER_LEN(out0, write); + out0->body.write.size = bufsize; + out.push_back(out0); + })); + + fd = open(FULLPATH, O_WRONLY); + ASSERT_LE(0, fd) << strerror(errno); + + setup_interruptor(self); + ASSERT_EQ(bufsize, write(fd, CONTENTS, bufsize)) << strerror(errno); + + /* Deliberately leak fd. close(2) will be tested in release.cc */ +} + +/* + * A syscall that gets interrupted while blocking on FUSE I/O should send a + * FUSE_INTERRUPT command to the fuse filesystem, which should then send EINTR + * in response to the _original_ operation. The kernel should ultimately + * return EINTR to userspace + */ +/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ +TEST_F(Interrupt, DISABLED_in_progress) +{ + const char FULLPATH[] = "mountpoint/some_file.txt"; + const char RELPATH[] = "some_file.txt"; + const char *CONTENTS = "abcdefgh"; + uint64_t ino = 42; + int fd; + ssize_t bufsize = strlen(CONTENTS); + pthread_t self; + uint64_t write_unique; + + self = pthread_self(); + + expect_lookup(RELPATH, ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); + expect_write(ino, &write_unique); + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + return (in->header.opcode == FUSE_INTERRUPT && + in->body.interrupt.unique == write_unique); + }, Eq(true)), + _) + ).WillOnce(Invoke([&](auto in __unused, auto &out) { + auto out0 = new mockfs_buf_out; + out0->header.error = -EINTR; + out0->header.unique = write_unique; + out0->header.len = sizeof(out0->header); + out.push_back(out0); + })); + + fd = open(FULLPATH, O_WRONLY); + ASSERT_LE(0, fd) << strerror(errno); + + setup_interruptor(self); + ASSERT_EQ(-1, write(fd, CONTENTS, bufsize)); + EXPECT_EQ(EINTR, errno); + + /* Deliberately leak fd. close(2) will be tested in release.cc */ +} + +/* + * If the FUSE filesystem receives the FUSE_INTERRUPT operation before + * processing the original, then it should wait for "some timeout" for the + * original operation to arrive. If not, it should send EAGAIN to the + * INTERRUPT operation, and the kernel should requeue the INTERRUPT. + * + * In this test, we'll pretend that the INTERRUPT arrives too soon, gets + * EAGAINed, then the kernel requeues it, and the second time around it + * successfully interrupts the original + */ +/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236530 */ +TEST_F(Interrupt, DISABLED_too_soon) +{ + const char FULLPATH[] = "mountpoint/some_file.txt"; + const char RELPATH[] = "some_file.txt"; + const char *CONTENTS = "abcdefgh"; + uint64_t ino = 42; + int fd; + ssize_t bufsize = strlen(CONTENTS); + pthread_t self; + uint64_t write_unique; + + self = pthread_self(); + + expect_lookup(RELPATH, ino); + expect_open(ino, 0, 1); + expect_getattr(ino, 0); + expect_write(ino, &write_unique); + + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + return (in->header.opcode == FUSE_INTERRUPT && + in->body.interrupt.unique == write_unique); + }, Eq(true)), + _) + ).WillOnce(Invoke(ReturnErrno(EAGAIN))) + .RetiresOnSaturation(); + + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + return (in->header.opcode == FUSE_INTERRUPT && + in->body.interrupt.unique == write_unique); + }, Eq(true)), + _) + ).WillOnce(Invoke([&](auto in __unused, auto &out __unused) { + auto out0 = new mockfs_buf_out; + out0->header.error = -EINTR; + out0->header.unique = write_unique; + out0->header.len = sizeof(out0->header); + out.push_back(out0); + })); + + fd = open(FULLPATH, O_WRONLY); + ASSERT_LE(0, fd) << strerror(errno); + + setup_interruptor(self); + ASSERT_EQ(-1, write(fd, CONTENTS, bufsize)); + EXPECT_EQ(EINTR, errno); + + /* Deliberately leak fd. close(2) will be tested in release.cc */ +} diff --git a/tests/sys/fs/fuse/link.cc b/tests/sys/fs/fuse/link.cc index 84944f42822..6ba606691fc 100644 --- a/tests/sys/fs/fuse/link.cc +++ b/tests/sys/fs/fuse/link.cc @@ -92,12 +92,12 @@ TEST_F(Link, ok) (0 == strcmp(name, RELPATH))); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).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; out->body.entry.nodeid = ino; - })); + }))); EXPECT_EQ(0, link(FULLDST, FULLPATH)) << strerror(errno); } diff --git a/tests/sys/fs/fuse/locks.cc b/tests/sys/fs/fuse/locks.cc index 6a6f8d8a304..e6d2e57cbda 100644 --- a/tests/sys/fs/fuse/locks.cc +++ b/tests/sys/fs/fuse/locks.cc @@ -123,12 +123,12 @@ TEST_F(Getlk, DISABLED_no_locks) in->body.getlk.lk.pid == 10); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).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; - })); + }))); fd = open(FULLPATH, O_RDWR); ASSERT_LE(0, fd) << strerror(errno); @@ -170,14 +170,14 @@ TEST_F(Getlk, DISABLED_lock_exists) in->body.getlk.lk.pid == 10); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, getlk); out->body.getlk.lk.start = 100; out->body.getlk.lk.end = 199; out->body.getlk.lk.type = F_WRLCK; out->body.getlk.lk.pid = (uint32_t)pid2;; - })); + }))); fd = open(FULLPATH, O_RDWR); ASSERT_LE(0, fd) << strerror(errno); @@ -251,12 +251,12 @@ TEST_F(Setlk, DISABLED_set) in->body.getlk.lk.pid == 10); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).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; - })); + }))); fd = open(FULLPATH, O_RDWR); ASSERT_LE(0, fd) << strerror(errno); @@ -296,12 +296,12 @@ TEST_F(Setlk, DISABLED_set_eof) in->body.getlk.lk.pid == 10); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).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; - })); + }))); fd = open(FULLPATH, O_RDWR); ASSERT_LE(0, fd) << strerror(errno); @@ -414,12 +414,12 @@ TEST_F(Setlkw, DISABLED_set) in->body.getlk.lk.pid == 10); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).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; - })); + }))); fd = open(FULLPATH, O_RDWR); ASSERT_LE(0, fd) << strerror(errno); diff --git a/tests/sys/fs/fuse/lookup.cc b/tests/sys/fs/fuse/lookup.cc index 86ab5d7d308..e478be267b5 100644 --- a/tests/sys/fs/fuse/lookup.cc +++ b/tests/sys/fs/fuse/lookup.cc @@ -52,7 +52,8 @@ TEST_F(Lookup, DISABLED_attr_cache) const uint64_t generation = 13; struct stat sb; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](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.nodeid = ino; @@ -72,7 +73,7 @@ TEST_F(Lookup, DISABLED_attr_cache) 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); EXPECT_EQ(1, sb.st_size); @@ -118,14 +119,15 @@ TEST_F(Lookup, attr_cache_timeout) */ long timeout_ns = 250'000'000; - EXPECT_LOOKUP(1, RELPATH).WillRepeatedly(Invoke([=](auto in, auto out) { + 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.nodeid = ino; out->body.entry.attr_valid_nsec = timeout_ns; out->body.entry.attr.ino = ino; // Must match nodeid out->body.entry.attr.mode = S_IFREG | 0644; - })); + }))); expect_getattr(ino, 0); /* access(2) will issue a VOP_LOOKUP but not a VOP_GETATTR */ @@ -154,13 +156,14 @@ TEST_F(Lookup, entry_cache) const char FULLPATH[] = "mountpoint/some_file.txt"; const char RELPATH[] = "some_file.txt"; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](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.entry_valid = UINT64_MAX; out->body.entry.attr.mode = S_IFREG | 0644; out->body.entry.nodeid = 14; - })); + }))); ASSERT_EQ(0, access(FULLPATH, F_OK)) << strerror(errno); /* The second access(2) should use the cache */ ASSERT_EQ(0, access(FULLPATH, F_OK)) << strerror(errno); @@ -224,13 +227,13 @@ TEST_F(Lookup, DISABLED_entry_cache_timeout) long timeout_ns = 250'000'000; EXPECT_LOOKUP(1, RELPATH).Times(2) - .WillRepeatedly(Invoke([=](auto in, auto out) { + .WillRepeatedly(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, entry); out->body.entry.entry_valid_nsec = timeout_ns; out->body.entry.attr.mode = S_IFREG | 0644; out->body.entry.nodeid = 14; - })); + }))); ASSERT_EQ(0, access(FULLPATH, F_OK)) << strerror(errno); usleep(2 * timeout_ns / 1000); /* The cache has timed out; VOP_LOOKUP should query the daemon*/ @@ -248,12 +251,13 @@ TEST_F(Lookup, ok) const char FULLPATH[] = "mountpoint/some_file.txt"; const char RELPATH[] = "some_file.txt"; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](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; out->body.entry.nodeid = 14; - })); + }))); /* * access(2) is one of the few syscalls that will not (always) follow * up a successful VOP_LOOKUP with another VOP. @@ -270,18 +274,20 @@ TEST_F(Lookup, subdir) uint64_t dir_ino = 2; uint64_t file_ino = 3; - EXPECT_LOOKUP(1, DIRPATH).WillOnce(Invoke([=](auto in, auto out) { + EXPECT_LOOKUP(1, DIRPATH) + .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_IFDIR | 0755; out->body.entry.nodeid = dir_ino; - })); - EXPECT_LOOKUP(dir_ino, RELPATH).WillOnce(Invoke([=](auto in, auto out) { + }))); + EXPECT_LOOKUP(dir_ino, 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; out->body.entry.nodeid = file_ino; - })); + }))); /* * access(2) is one of the few syscalls that will not (always) follow * up a successful VOP_LOOKUP with another VOP. diff --git a/tests/sys/fs/fuse/mkdir.cc b/tests/sys/fs/fuse/mkdir.cc index 2066c33eb2a..ea148af5b94 100644 --- a/tests/sys/fs/fuse/mkdir.cc +++ b/tests/sys/fs/fuse/mkdir.cc @@ -95,14 +95,14 @@ TEST_F(Mkdir, DISABLED_entry_cache_negative) (0 == strcmp(RELPATH, name))); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, entry); out->body.create.entry.attr.mode = S_IFDIR | mode; out->body.create.entry.nodeid = ino; out->body.create.entry.entry_valid = UINT64_MAX; out->body.create.entry.attr_valid = UINT64_MAX; - })); + }))); ASSERT_EQ(0, mkdir(FULLPATH, mode)) << strerror(errno); } @@ -134,13 +134,13 @@ TEST_F(Mkdir, DISABLED_entry_cache_negative_purge) (0 == strcmp(RELPATH, name))); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).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_IFDIR | mode; out->body.entry.nodeid = ino; out->body.entry.attr_valid = UINT64_MAX; - })); + }))); ASSERT_EQ(0, mkdir(FULLPATH, mode)) << strerror(errno); @@ -168,14 +168,14 @@ TEST_F(Mkdir, ok) (0 == strcmp(RELPATH, name))); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, entry); out->body.create.entry.attr.mode = S_IFDIR | mode; out->body.create.entry.nodeid = ino; out->body.create.entry.entry_valid = UINT64_MAX; out->body.create.entry.attr_valid = UINT64_MAX; - })); + }))); ASSERT_EQ(0, mkdir(FULLPATH, mode)) << strerror(errno); } diff --git a/tests/sys/fs/fuse/mknod.cc b/tests/sys/fs/fuse/mknod.cc index 078d67d03d2..2101d10c7df 100644 --- a/tests/sys/fs/fuse/mknod.cc +++ b/tests/sys/fs/fuse/mknod.cc @@ -67,7 +67,7 @@ void test_ok(mode_t mode, dev_t dev) { (0 == strcmp(RELPATH, name))); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, create); out->body.create.entry.attr.mode = mode; @@ -75,7 +75,7 @@ void test_ok(mode_t mode, dev_t dev) { out->body.create.entry.entry_valid = UINT64_MAX; out->body.create.entry.attr_valid = UINT64_MAX; out->body.create.entry.attr.rdev = dev; - })); + }))); EXPECT_EQ(0, mknod(FULLPATH, mode, dev)) << strerror(errno); } diff --git a/tests/sys/fs/fuse/mockfs.cc b/tests/sys/fs/fuse/mockfs.cc index 8f67a45ecb9..a098b336f00 100644 --- a/tests/sys/fs/fuse/mockfs.cc +++ b/tests/sys/fs/fuse/mockfs.cc @@ -105,28 +105,43 @@ const char* opcode2opname(uint32_t opcode) return (table[opcode]); } -std::function +ProcessMockerT ReturnErrno(int error) { - return([=](auto in, auto out) { - out->header.unique = in->header.unique; - out->header.error = -error; - out->header.len = sizeof(out->header); + return([=](auto in, auto &out) { + auto out0 = new mockfs_buf_out; + out0->header.unique = in->header.unique; + out0->header.error = -error; + out0->header.len = sizeof(out0->header); + out.push_back(out0); }); } /* Helper function used for returning negative cache entries for LOOKUP */ -std::function +ProcessMockerT ReturnNegativeCache(const struct timespec *entry_valid) { - return([=](auto in, auto out) { + return([=](auto in, auto &out) { /* nodeid means ENOENT and cache it */ - out->body.entry.nodeid = 0; - out->header.unique = in->header.unique; - out->header.error = 0; - out->body.entry.entry_valid = entry_valid->tv_sec; - out->body.entry.entry_valid_nsec = entry_valid->tv_nsec; - SET_OUT_HEADER_LEN(out, entry); + auto out0 = new mockfs_buf_out; + out0->body.entry.nodeid = 0; + out0->header.unique = in->header.unique; + out0->header.error = 0; + out0->body.entry.entry_valid = entry_valid->tv_sec; + out0->body.entry.entry_valid_nsec = entry_valid->tv_nsec; + SET_OUT_HEADER_LEN(out0, entry); + out.push_back(out0); + }); +} + +ProcessMockerT +ReturnImmediate(std::function f) +{ + return([=](auto in, auto &out) { + auto out0 = new mockfs_buf_out; + f(in, out0); + out.push_back(out0); }); } @@ -309,14 +324,12 @@ void MockFS::kill_daemon() { void MockFS::loop() { mockfs_buf_in *in; - mockfs_buf_out *out; + std::vector out; in = (mockfs_buf_in*) malloc(sizeof(*in)); - out = (mockfs_buf_out*) malloc(sizeof(*out)); ASSERT_TRUE(in != NULL); while (!quit) { bzero(in, sizeof(*in)); - bzero(out, sizeof(*out)); read_request(in); if (quit) break; @@ -332,19 +345,14 @@ void MockFS::loop() { */ process_default(in, out); } - if (in->header.opcode == FUSE_FORGET) { - /*Alone among the opcodes, FORGET expects no response*/ - continue; - } - if (out->header.error == FUSE_NORESPONSE) { - /* Used by tests of slow opcodes. No response ATM */ - continue; + for (auto &it: out) { + ASSERT_TRUE(write(m_fuse_fd, it, it->header.len) > 0 || + errno == EAGAIN) + << strerror(errno); + delete it; } - ASSERT_TRUE(write(m_fuse_fd, out, out->header.len) > 0 || - errno == EAGAIN) - << strerror(errno); + out.clear(); } - free(out); free(in); } @@ -369,10 +377,14 @@ bool MockFS::pid_ok(pid_t pid) { } } -void MockFS::process_default(const mockfs_buf_in *in, mockfs_buf_out* out) { - out->header.unique = in->header.unique; - out->header.error = -EOPNOTSUPP; - out->header.len = sizeof(out->header); +void MockFS::process_default(const mockfs_buf_in *in, + std::vector &out) +{ + auto out0 = new mockfs_buf_out; + out0->header.unique = in->header.unique; + out0->header.error = -EOPNOTSUPP; + out0->header.len = sizeof(out0->header); + out.push_back(out0); } void MockFS::read_request(mockfs_buf_in *in) { diff --git a/tests/sys/fs/fuse/mockfs.hh b/tests/sys/fs/fuse/mockfs.hh index 4ce66e28c8f..dbf217ba0f2 100644 --- a/tests/sys/fs/fuse/mockfs.hh +++ b/tests/sys/fs/fuse/mockfs.hh @@ -132,11 +132,16 @@ union fuse_payloads_out { struct mockfs_buf_out { fuse_out_header header; union fuse_payloads_out body; + + /* Default constructor: zero everything */ + mockfs_buf_out() { + memset(this, 0, sizeof(*this)); + } }; /* A function that can be invoked in place of MockFS::process */ typedef std::function + std::vector &out)> ProcessMockerT; /* @@ -146,8 +151,12 @@ ProcessMockerT; ProcessMockerT ReturnErrno(int error); /* Helper function used for returning negative cache entries for LOOKUP */ -std::function -ReturnNegativeCache(const struct timespec *entry_valid); +ProcessMockerT ReturnNegativeCache(const struct timespec *entry_valid); + +/* Helper function used for returning a single immediate response */ +ProcessMockerT ReturnImmediate( + std::function f); /* * Fake FUSE filesystem @@ -182,7 +191,8 @@ class MockFS { bool pid_ok(pid_t pid); /* Default request handler */ - void process_default(const mockfs_buf_in*, mockfs_buf_out*); + void process_default(const mockfs_buf_in*, + std::vector&); /* Entry point for the daemon thread */ static void* service(void*); @@ -207,12 +217,14 @@ class MockFS { /* * Request handler * - * This method is expected to provide the response to each FUSE - * operation. Responses must be immediate (so this method can't be used - * for testing a daemon with queue depth > 1). Test cases must define - * each response using Googlemock expectations + * This method is expected to provide the responses to each FUSE + * operation. For an immediate response, push one buffer into out. + * For a delayed response, push nothing. For an immediate response + * plus a delayed response to an earlier operation, push two bufs. + * Test cases must define each response using Googlemock expectations */ - MOCK_METHOD2(process, void(const mockfs_buf_in*, mockfs_buf_out*)); + MOCK_METHOD2(process, void(const mockfs_buf_in*, + std::vector&)); /* Gracefully unmount */ void unmount(); diff --git a/tests/sys/fs/fuse/open.cc b/tests/sys/fs/fuse/open.cc index 1b1aa0d899a..19d6ddbf24e 100644 --- a/tests/sys/fs/fuse/open.cc +++ b/tests/sys/fs/fuse/open.cc @@ -56,11 +56,11 @@ void test_ok(int os_flags, int fuse_flags) { in->header.nodeid == ino); }, Eq(true)), _) - ).WillOnce(Invoke([](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([](auto in, auto out) { out->header.unique = in->header.unique; out->header.len = sizeof(out->header); SET_OUT_HEADER_LEN(out, open); - })); + }))); /* Until the attr cache is working, we may send an additional GETATTR */ EXPECT_CALL(*m_mock, process( @@ -69,12 +69,12 @@ void test_ok(int os_flags, int fuse_flags) { in->header.nodeid == ino); }, Eq(true)), _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { + ).WillRepeatedly(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 | 0644; - })); + }))); fd = open(FULLPATH, os_flags); EXPECT_LE(0, fd) << strerror(errno); diff --git a/tests/sys/fs/fuse/opendir.cc b/tests/sys/fs/fuse/opendir.cc index d15e5138654..948bfd27d72 100644 --- a/tests/sys/fs/fuse/opendir.cc +++ b/tests/sys/fs/fuse/opendir.cc @@ -109,10 +109,10 @@ TEST_F(Opendir, open) in->header.nodeid == ino); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, open); - })); + }))); EXPECT_LE(0, open(FULLPATH, O_DIRECTORY)) << strerror(errno); } @@ -129,10 +129,10 @@ TEST_F(Opendir, opendir) return (in->header.opcode == FUSE_STATFS); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, statfs); - })); + }))); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { @@ -140,10 +140,10 @@ TEST_F(Opendir, opendir) in->header.nodeid == ino); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, open); - })); + }))); errno = 0; EXPECT_NE(NULL, opendir(FULLPATH)) << strerror(errno); diff --git a/tests/sys/fs/fuse/read.cc b/tests/sys/fs/fuse/read.cc index 1a684270645..a41301b4c67 100644 --- a/tests/sys/fs/fuse/read.cc +++ b/tests/sys/fs/fuse/read.cc @@ -242,11 +242,11 @@ TEST_F(Read, mmap) in->body.read.size >= bufsize); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; out->header.len = sizeof(struct fuse_out_header) + bufsize; memmove(out->body.bytes, CONTENTS, bufsize); - })); + }))); fd = open(FULLPATH, O_RDONLY); ASSERT_LE(0, fd) << strerror(errno); @@ -411,11 +411,11 @@ TEST_F(Read, sendfile) in->body.read.size >= bufsize); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; out->header.len = sizeof(struct fuse_out_header) + bufsize; memmove(out->body.bytes, CONTENTS, bufsize); - })); + }))); ASSERT_EQ(0, socketpair(PF_LOCAL, SOCK_STREAM, 0, sp)) << strerror(errno); diff --git a/tests/sys/fs/fuse/readdir.cc b/tests/sys/fs/fuse/readdir.cc index 641a2ef19aa..ee9556984a0 100644 --- a/tests/sys/fs/fuse/readdir.cc +++ b/tests/sys/fs/fuse/readdir.cc @@ -55,7 +55,7 @@ void expect_readdir(uint64_t ino, uint64_t off, vector &ents) in->body.readdir.offset == off); }, Eq(true)), _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { + ).WillRepeatedly(Invoke(ReturnImmediate([=](auto in, auto out) { struct fuse_dirent *fde = (struct fuse_dirent*)out->body.bytes; int i = 0; @@ -92,7 +92,7 @@ void expect_readdir(uint64_t ino, uint64_t off, vector &ents) i++; } out->header.len += sizeof(out->header); - })); + }))); } }; @@ -208,11 +208,11 @@ TEST_F(Readdir, nodots) in->header.nodeid == ino); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; out->header.error = 0; out->header.len = sizeof(out->header); - })); + }))); errno = 0; dir = opendir(FULLPATH); diff --git a/tests/sys/fs/fuse/readlink.cc b/tests/sys/fs/fuse/readlink.cc index ff3490f4e1a..203b21149c2 100644 --- a/tests/sys/fs/fuse/readlink.cc +++ b/tests/sys/fs/fuse/readlink.cc @@ -82,11 +82,11 @@ TEST_F(Readlink, ok) in->header.nodeid == ino); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; strlcpy(out->body.str, dst, sizeof(out->body.str)); out->header.len = sizeof(out->header) + strlen(dst) + 1; - })); + }))); EXPECT_EQ((ssize_t)strlen(dst) + 1, diff --git a/tests/sys/fs/fuse/releasedir.cc b/tests/sys/fs/fuse/releasedir.cc index e2b10dd3e10..fc4f15a263c 100644 --- a/tests/sys/fs/fuse/releasedir.cc +++ b/tests/sys/fs/fuse/releasedir.cc @@ -75,11 +75,11 @@ TEST_F(ReleaseDir, dup) in->body.readdir.offset == 0); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; out->header.error = 0; out->header.len = sizeof(out->header); - })); + }))); expect_releasedir(ino, ReturnErrno(0)); dir = opendir(FULLPATH); diff --git a/tests/sys/fs/fuse/rmdir.cc b/tests/sys/fs/fuse/rmdir.cc index 6f35c33dfd9..5ab958563d4 100644 --- a/tests/sys/fs/fuse/rmdir.cc +++ b/tests/sys/fs/fuse/rmdir.cc @@ -41,13 +41,14 @@ class Rmdir: public FuseTest { public: void expect_lookup(const char *relpath, uint64_t ino) { - EXPECT_LOOKUP(1, relpath).WillOnce(Invoke([=](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_IFDIR | 0755; out->body.entry.nodeid = ino; out->body.entry.attr.nlink = 2; - })); + }))); } }; diff --git a/tests/sys/fs/fuse/setattr.cc b/tests/sys/fs/fuse/setattr.cc index b20a160572e..5e0202fc49a 100644 --- a/tests/sys/fs/fuse/setattr.cc +++ b/tests/sys/fs/fuse/setattr.cc @@ -51,13 +51,14 @@ TEST_F(Setattr, chmod) const mode_t oldmode = 0755; const mode_t newmode = 0644; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](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 | oldmode; out->body.entry.nodeid = ino; out->body.entry.attr.mode = S_IFREG | oldmode; - })); + }))); EXPECT_CALL(*m_mock, process( ResultOf([](auto in) { @@ -69,12 +70,12 @@ TEST_F(Setattr, chmod) in->body.setattr.mode == newmode); }, Eq(true)), _) - ).WillOnce(Invoke([](auto in, auto out) { + ).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_EQ(0, chmod(FULLPATH, newmode)) << strerror(errno); } @@ -89,14 +90,15 @@ TEST_F(Setattr, chown) const uid_t olduser = 33; const uid_t newuser = 44; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](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; out->body.entry.nodeid = ino; out->body.entry.attr.gid = oldgroup; out->body.entry.attr.uid = olduser; - })); + }))); EXPECT_CALL(*m_mock, process( ResultOf([](auto in) { @@ -109,14 +111,14 @@ TEST_F(Setattr, chown) in->body.setattr.gid == newgroup); }, Eq(true)), _) - ).WillOnce(Invoke([](auto in, auto out) { + ).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 | 0644; out->body.attr.attr.uid = newuser; out->body.attr.attr.gid = newgroup; - })); + }))); EXPECT_EQ(0, chown(FULLPATH, newuser, newgroup)) << strerror(errno); } @@ -133,14 +135,15 @@ TEST_F(Setattr, eperm) const char RELPATH[] = "some_file.txt"; const uint64_t ino = 42; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](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 | 0777; out->body.entry.nodeid = ino; out->body.entry.attr.uid = in->header.uid; out->body.entry.attr.gid = in->header.gid; - })); + }))); EXPECT_CALL(*m_mock, process( ResultOf([](auto in) { @@ -163,13 +166,14 @@ TEST_F(Setattr, fchmod) const mode_t oldmode = 0755; const mode_t newmode = 0644; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](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 | oldmode; out->body.entry.nodeid = ino; out->body.entry.attr_valid = UINT64_MAX; - })); + }))); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { @@ -177,11 +181,11 @@ TEST_F(Setattr, fchmod) in->header.nodeid == ino); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; out->header.len = sizeof(out->header); SET_OUT_HEADER_LEN(out, open); - })); + }))); /* Until the attr cache is working, we may send an additional GETATTR */ EXPECT_CALL(*m_mock, process( @@ -190,12 +194,12 @@ TEST_F(Setattr, fchmod) in->header.nodeid == ino); }, Eq(true)), _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { + ).WillRepeatedly(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 | oldmode; - })); + }))); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { @@ -207,12 +211,12 @@ TEST_F(Setattr, fchmod) in->body.setattr.mode == newmode); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).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; - })); + }))); fd = open(FULLPATH, O_RDONLY); ASSERT_LE(0, fd) << strerror(errno); @@ -231,14 +235,15 @@ TEST_F(Setattr, ftruncate) const off_t oldsize = 99; const off_t newsize = 12345; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](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 | 0755; out->body.entry.nodeid = ino; out->body.entry.attr_valid = UINT64_MAX; out->body.entry.attr.size = oldsize; - })); + }))); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { @@ -246,12 +251,12 @@ TEST_F(Setattr, ftruncate) in->header.nodeid == ino); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](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; - })); + }))); /* Until the attr cache is working, we may send an additional GETATTR */ EXPECT_CALL(*m_mock, process( @@ -260,13 +265,13 @@ TEST_F(Setattr, ftruncate) in->header.nodeid == ino); }, Eq(true)), _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { + ).WillRepeatedly(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 | 0755; out->body.attr.attr.size = oldsize; - })); + }))); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { @@ -278,13 +283,13 @@ TEST_F(Setattr, ftruncate) in->body.setattr.fh == fh); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).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 | 0755; out->body.attr.attr.size = newsize; - })); + }))); fd = open(FULLPATH, O_RDWR); ASSERT_LE(0, fd) << strerror(errno); @@ -300,13 +305,13 @@ TEST_F(Setattr, truncate) { const uint64_t oldsize = 100'000'000; const uint64_t newsize = 20'000'000; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](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; out->body.entry.nodeid = ino; out->body.entry.attr.size = oldsize; - })); + }))); EXPECT_CALL(*m_mock, process( ResultOf([](auto in) { @@ -318,13 +323,13 @@ TEST_F(Setattr, truncate) { in->body.setattr.size == newsize); }, Eq(true)), _) - ).WillOnce(Invoke([](auto in, auto out) { + ).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 | 0644; out->body.attr.attr.size = newsize; - })); + }))); EXPECT_EQ(0, truncate(FULLPATH, newsize)) << strerror(errno); } @@ -342,7 +347,7 @@ TEST_F(Setattr, utimensat) { {.tv_sec = 7, .tv_nsec = 8}, }; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](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; @@ -352,7 +357,7 @@ TEST_F(Setattr, utimensat) { out->body.entry.attr.atimensec = oldtimes[0].tv_nsec; out->body.entry.attr.mtime = oldtimes[1].tv_sec; out->body.entry.attr.mtimensec = oldtimes[1].tv_nsec; - })); + }))); /* * Until bug 235775 is fixed, utimensat will make an extra FUSE_GETATTR @@ -364,7 +369,7 @@ TEST_F(Setattr, utimensat) { in->header.nodeid == ino); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).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 @@ -373,7 +378,7 @@ TEST_F(Setattr, utimensat) { out->body.attr.attr.atimensec = oldtimes[0].tv_nsec; out->body.attr.attr.mtime = oldtimes[1].tv_sec; out->body.attr.attr.mtimensec = oldtimes[1].tv_nsec; - })); + }))); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { @@ -390,7 +395,7 @@ TEST_F(Setattr, utimensat) { newtimes[1].tv_nsec); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).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 @@ -399,7 +404,7 @@ TEST_F(Setattr, utimensat) { out->body.attr.attr.atimensec = newtimes[0].tv_nsec; out->body.attr.attr.mtime = newtimes[1].tv_sec; out->body.attr.attr.mtimensec = newtimes[1].tv_nsec; - })); + }))); EXPECT_EQ(0, utimensat(AT_FDCWD, FULLPATH, &newtimes[0], 0)) << strerror(errno); } @@ -418,7 +423,7 @@ TEST_F(Setattr, utimensat_mtime_only) { {.tv_sec = 7, .tv_nsec = 8}, }; - EXPECT_LOOKUP(1, RELPATH).WillOnce(Invoke([=](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; @@ -428,7 +433,7 @@ TEST_F(Setattr, utimensat_mtime_only) { out->body.entry.attr.atimensec = oldtimes[0].tv_nsec; out->body.entry.attr.mtime = oldtimes[1].tv_sec; out->body.entry.attr.mtimensec = oldtimes[1].tv_nsec; - })); + }))); /* * Until bug 235775 is fixed, utimensat will make an extra FUSE_GETATTR @@ -440,7 +445,7 @@ TEST_F(Setattr, utimensat_mtime_only) { in->header.nodeid == ino); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).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 @@ -449,7 +454,7 @@ TEST_F(Setattr, utimensat_mtime_only) { out->body.attr.attr.atimensec = oldtimes[0].tv_nsec; out->body.attr.attr.mtime = oldtimes[1].tv_sec; out->body.attr.attr.mtimensec = oldtimes[1].tv_nsec; - })); + }))); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { @@ -463,7 +468,7 @@ TEST_F(Setattr, utimensat_mtime_only) { newtimes[1].tv_nsec); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).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 @@ -472,7 +477,7 @@ TEST_F(Setattr, utimensat_mtime_only) { out->body.attr.attr.atimensec = oldtimes[0].tv_nsec; out->body.attr.attr.mtime = newtimes[1].tv_sec; out->body.attr.attr.mtimensec = newtimes[1].tv_nsec; - })); + }))); EXPECT_EQ(0, utimensat(AT_FDCWD, FULLPATH, &newtimes[0], 0)) << strerror(errno); } diff --git a/tests/sys/fs/fuse/statfs.cc b/tests/sys/fs/fuse/statfs.cc index a7268abd655..e4bf6cdd0e1 100644 --- a/tests/sys/fs/fuse/statfs.cc +++ b/tests/sys/fs/fuse/statfs.cc @@ -86,7 +86,7 @@ TEST_F(Statfs, ok) return (in->header.opcode == FUSE_STATFS); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, statfs); out->body.statfs.st.blocks = 1000; @@ -96,7 +96,7 @@ TEST_F(Statfs, ok) out->body.statfs.st.ffree = 6; out->body.statfs.st.namelen = 128; out->body.statfs.st.frsize = 1024; - })); + }))); ASSERT_NE(NULL, getcwd(mp, PATH_MAX)) << strerror(errno); strlcat(mp, "/mountpoint", PATH_MAX); diff --git a/tests/sys/fs/fuse/symlink.cc b/tests/sys/fs/fuse/symlink.cc index 2c9a0deab25..3515c3f18cf 100644 --- a/tests/sys/fs/fuse/symlink.cc +++ b/tests/sys/fs/fuse/symlink.cc @@ -80,12 +80,12 @@ TEST_F(Symlink, ok) (0 == strcmp(name, RELPATH))); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).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_IFLNK | 0777; out->body.entry.nodeid = ino; - })); + }))); EXPECT_EQ(0, symlink(dst, FULLPATH)) << strerror(errno); } diff --git a/tests/sys/fs/fuse/utils.cc b/tests/sys/fs/fuse/utils.cc index 300f2daf8ad..93f5c547fd1 100644 --- a/tests/sys/fs/fuse/utils.cc +++ b/tests/sys/fs/fuse/utils.cc @@ -93,14 +93,14 @@ void FuseTest::expect_getattr(uint64_t ino, uint64_t size) in->header.nodeid == ino); }, Eq(true)), _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { + ).WillRepeatedly(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 | 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, @@ -108,14 +108,14 @@ void FuseTest::expect_lookup(const char *relpath, uint64_t ino, mode_t mode, { EXPECT_LOOKUP(1, relpath) .Times(times) - .WillRepeatedly(Invoke([=](auto in, auto out) { + .WillRepeatedly(Invoke(ReturnImmediate([=](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) @@ -127,13 +127,13 @@ void FuseTest::expect_open(uint64_t ino, uint32_t flags, int times) }, Eq(true)), _) ).Times(times) - .WillRepeatedly(Invoke([=](auto in, auto out) { + .WillRepeatedly(Invoke(ReturnImmediate([=](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) @@ -143,10 +143,10 @@ void FuseTest::expect_opendir(uint64_t ino) return (in->header.opcode == FUSE_STATFS); }, Eq(true)), _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { + ).WillRepeatedly(Invoke(ReturnImmediate([=](auto in, auto out) { out->header.unique = in->header.unique; SET_OUT_HEADER_LEN(out, statfs); - })); + }))); EXPECT_CALL(*m_mock, process( ResultOf([=](auto in) { @@ -154,12 +154,12 @@ void FuseTest::expect_opendir(uint64_t ino) in->header.nodeid == ino); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](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, @@ -174,11 +174,11 @@ void FuseTest::expect_read(uint64_t ino, uint64_t offset, uint64_t isize, in->body.read.size == isize); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](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(); + }))).RetiresOnSaturation(); } void FuseTest::expect_release(uint64_t ino, int times, int error) @@ -217,11 +217,11 @@ void FuseTest::expect_write(uint64_t ino, uint64_t offset, uint64_t isize, 0 == bcmp(buf, contents, isize)); }, Eq(true)), _) - ).WillOnce(Invoke([=](auto in, auto out) { + ).WillOnce(Invoke(ReturnImmediate([=](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) { diff --git a/tests/sys/fs/fuse/write.cc b/tests/sys/fs/fuse/write.cc index d671e40586a..6d8dd1793d4 100644 --- a/tests/sys/fs/fuse/write.cc +++ b/tests/sys/fs/fuse/write.cc @@ -503,11 +503,11 @@ TEST_F(WriteBack, close) return (in->header.opcode == FUSE_SETATTR); }, Eq(true)), _) - ).WillRepeatedly(Invoke([=](auto in, auto out) { + ).WillRepeatedly(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 - })); + }))); expect_release(ino, ReturnErrno(0)); fd = open(FULLPATH, O_RDWR); @@ -635,14 +635,14 @@ TEST_F(WriteThrough, DISABLED_update_file_size) }, Eq(true)), _) ).Times(2) - .WillRepeatedly(Invoke([=](auto in, auto out) { + .WillRepeatedly(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 | 0644; out->body.attr.attr.size = 0; out->body.attr.attr_valid = UINT64_MAX; - })); + }))); expect_write(ino, 0, bufsize, bufsize, 0, CONTENTS); fd = open(FULLPATH, O_RDWR); -- 2.45.0