From owner-svn-src-projects@freebsd.org Tue Mar 5 18:53:30 2019 Return-Path: Delivered-To: svn-src-projects@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 39634150D5FD for ; Tue, 5 Mar 2019 18:53:30 +0000 (UTC) (envelope-from asomers@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id D29F282A5C; Tue, 5 Mar 2019 18:53:29 +0000 (UTC) (envelope-from asomers@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id ADDCB2032C; Tue, 5 Mar 2019 18:53:29 +0000 (UTC) (envelope-from asomers@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x25IrTrI057375; Tue, 5 Mar 2019 18:53:29 GMT (envelope-from asomers@FreeBSD.org) Received: (from asomers@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x25IrSlT057371; Tue, 5 Mar 2019 18:53:28 GMT (envelope-from asomers@FreeBSD.org) Message-Id: <201903051853.x25IrSlT057371@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: asomers set sender to asomers@FreeBSD.org using -f From: Alan Somers Date: Tue, 5 Mar 2019 18:53:28 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r344812 - projects/fuse2/tests/sys/fs/fuse X-SVN-Group: projects X-SVN-Commit-Author: asomers X-SVN-Commit-Paths: projects/fuse2/tests/sys/fs/fuse X-SVN-Commit-Revision: 344812 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: D29F282A5C X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.97 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-1.000,0]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; NEURAL_HAM_SHORT(-0.97)[-0.970,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US] X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 05 Mar 2019 18:53:30 -0000 Author: asomers Date: Tue Mar 5 18:53:28 2019 New Revision: 344812 URL: https://svnweb.freebsd.org/changeset/base/344812 Log: fuse(4): add tests for FUSE_MKDIR and FUSE_ACCESS PR: 236291 PR: 236231 Sponsored by: The FreeBSD Foundation Added: projects/fuse2/tests/sys/fs/fuse/access.cc (contents, props changed) projects/fuse2/tests/sys/fs/fuse/mkdir.cc (contents, props changed) Modified: projects/fuse2/tests/sys/fs/fuse/Makefile projects/fuse2/tests/sys/fs/fuse/mockfs.hh Modified: projects/fuse2/tests/sys/fs/fuse/Makefile ============================================================================== --- projects/fuse2/tests/sys/fs/fuse/Makefile Tue Mar 5 18:52:13 2019 (r344811) +++ projects/fuse2/tests/sys/fs/fuse/Makefile Tue Mar 5 18:53:28 2019 (r344812) @@ -4,16 +4,22 @@ PACKAGE= tests TESTSDIR= ${TESTSBASE}/sys/fs/fuse +ATF_TESTS_CXX+= access ATF_TESTS_CXX+= create ATF_TESTS_CXX+= getattr ATF_TESTS_CXX+= lookup -#ATF_TESTS_CXX+= mkdir +ATF_TESTS_CXX+= mkdir ATF_TESTS_CXX+= mknod ATF_TESTS_CXX+= open ATF_TESTS_CXX+= readlink ATF_TESTS_CXX+= setattr ATF_TESTS_CXX+= symlink +SRCS.access+= access.cc +SRCS.access+= getmntopts.c +SRCS.access+= mockfs.cc +SRCS.access+= utils.cc + SRCS.create+= create.cc SRCS.create+= getmntopts.c SRCS.create+= mockfs.cc @@ -29,10 +35,10 @@ SRCS.lookup+= lookup.cc SRCS.lookup+= mockfs.cc SRCS.lookup+= utils.cc -#SRCS.mkdir+= getmntopts.c -#SRCS.mkdir+= mockfs.cc -#SRCS.mkdir+= mkdir.cc -#SRCS.mkdir+= utils.cc +SRCS.mkdir+= getmntopts.c +SRCS.mkdir+= mockfs.cc +SRCS.mkdir+= mkdir.cc +SRCS.mkdir+= utils.cc SRCS.mknod+= getmntopts.c SRCS.mknod+= mockfs.cc Added: projects/fuse2/tests/sys/fs/fuse/access.cc ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/fuse2/tests/sys/fs/fuse/access.cc Tue Mar 5 18:53:28 2019 (r344812) @@ -0,0 +1,99 @@ +/*- + * Copyright (c) 2019 The FreeBSD Foundation + * All rights reserved. + * + * 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; + +class Access: public FuseTest {}; + +/* TODO: test methods for the default_permissions mount option */ + +/* The error case of FUSE_ACCESS. */ +/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236291 */ +TEST_F(Access, DISABLED_eaccess) +{ + const char FULLPATH[] = "mountpoint/some_file.txt"; + const char RELPATH[] = "some_file.txt"; + uint64_t ino = 42; + mode_t access_mode = X_OK; + + EXPECT_LOOKUP(RELPATH).WillOnce(Invoke([=](auto in, auto out) { + out->header.unique = in->header.unique; + SET_OUT_HEADER_LEN(out, entry); + out->body.entry.attr.mode = S_IFREG | 0644; + out->body.entry.nodeid = ino; + })); + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + return (in->header.opcode == FUSE_ACCESS && + in->header.nodeid == ino && + in->body.access.mask == access_mode); + }, Eq(true)), + _) + ).WillOnce(Invoke(ReturnErrno(EACCES))); + + + ASSERT_NE(0, access(FULLPATH, access_mode)); + ASSERT_EQ(EACCES, errno); +} + +/* The successful case of FUSE_ACCESS. */ +/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236291 */ +TEST_F(Access, DISABLED_ok) +{ + const char FULLPATH[] = "mountpoint/some_file.txt"; + const char RELPATH[] = "some_file.txt"; + uint64_t ino = 42; + mode_t access_mode = R_OK; + + EXPECT_LOOKUP(RELPATH).WillOnce(Invoke([=](auto in, auto out) { + out->header.unique = in->header.unique; + SET_OUT_HEADER_LEN(out, entry); + out->body.entry.attr.mode = S_IFREG | 0644; + out->body.entry.nodeid = ino; + })); + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + return (in->header.opcode == FUSE_ACCESS && + in->header.nodeid == ino && + in->body.access.mask == access_mode); + }, Eq(true)), + _) + ).WillOnce(Invoke(ReturnErrno(0))); + + ASSERT_EQ(0, access(FULLPATH, access_mode)) << strerror(errno); +} Added: projects/fuse2/tests/sys/fs/fuse/mkdir.cc ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/fuse2/tests/sys/fs/fuse/mkdir.cc Tue Mar 5 18:53:28 2019 (r344812) @@ -0,0 +1,198 @@ +/*- + * Copyright (c) 2019 The FreeBSD Foundation + * All rights reserved. + * + * 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 "mockfs.hh" +#include "utils.hh" + +using namespace testing; + +class Mkdir: public FuseTest {}; + +/* + * EMLINK is possible on filesystems that limit the number of hard links to a + * single file, like early versions of BtrFS + */ +TEST_F(Mkdir, emlink) +{ + const char FULLPATH[] = "mountpoint/some_dir"; + const char RELPATH[] = "some_dir"; + mode_t mode = 0755; + + EXPECT_LOOKUP(RELPATH).WillOnce(Invoke(ReturnErrno(ENOENT))); + + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + const char *name = (const char*)in->body.bytes + + sizeof(fuse_mkdir_in); + return (in->header.opcode == FUSE_MKDIR && + in->body.mkdir.mode == (S_IFDIR | mode) && + (0 == strcmp(RELPATH, name))); + }, Eq(true)), + _) + ).WillOnce(Invoke(ReturnErrno(EMLINK))); + + ASSERT_NE(1, mkdir(FULLPATH, mode)); + ASSERT_EQ(EMLINK, errno); +} + +/* + * Creating a new directory after FUSE_LOOKUP returned a negative cache entry + */ +/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236231 */ +TEST_F(Mkdir, DISABLED_entry_cache_negative) +{ + const char FULLPATH[] = "mountpoint/some_file.txt"; + const char RELPATH[] = "some_file.txt"; + mode_t mode = 0755; + uint64_t ino = 42; + + /* mkdir will first do a LOOKUP, adding a negative cache entry */ + EXPECT_LOOKUP(RELPATH).WillOnce(Invoke([=](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; + /* + * Set entry_valid = 0 because this test isn't concerned with + * whether or not we actually cache negative entries, only with + * whether we interpret negative cache responses correctly. + */ + out->body.entry.entry_valid = 0; + SET_OUT_HEADER_LEN(out, entry); + })); + + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + const char *name = (const char*)in->body.bytes + + sizeof(fuse_open_in); + return (in->header.opcode == FUSE_MKDIR && + in->body.mkdir.mode == (S_IFDIR | mode) && + (0 == strcmp(RELPATH, name))); + }, Eq(true)), + _) + ).WillOnce(Invoke([=](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); +} + +/* + * Creating a new directory should purge any negative namecache entries + */ +/* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236231 */ +TEST_F(Mkdir, DISABLED_entry_cache_negative_purge) +{ + const char FULLPATH[] = "mountpoint/some_file.txt"; + const char RELPATH[] = "some_file.txt"; + mode_t mode = 0755; + uint64_t ino = 42; + + /* mkdir will first do a LOOKUP, adding a negative cache entry */ + EXPECT_LOOKUP(RELPATH).Times(1) + .WillOnce(Invoke([=](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 = UINT64_MAX; + SET_OUT_HEADER_LEN(out, entry); + })).RetiresOnSaturation(); + + /* Then the MKDIR should purge the negative cache entry */ + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + const char *name = (const char*)in->body.bytes + + sizeof(fuse_open_in); + return (in->header.opcode == FUSE_MKDIR && + in->body.mkdir.mode == (S_IFDIR | mode) && + (0 == strcmp(RELPATH, name))); + }, Eq(true)), + _) + ).WillOnce(Invoke([=](auto in, auto out) { + out->header.unique = in->header.unique; + SET_OUT_HEADER_LEN(out, entry); + out->body.entry.attr.mode = S_IFDIR | mode; + out->body.entry.nodeid = ino; + out->body.entry.attr_valid = UINT64_MAX; + })); + + ASSERT_EQ(0, mkdir(FULLPATH, mode)) << strerror(errno); + + /* Finally, a subsequent lookup should query the daemon */ + EXPECT_LOOKUP(RELPATH).Times(1) + .WillOnce(Invoke([=](auto in, auto out) { + out->header.unique = in->header.unique; + out->header.error = 0; + out->body.entry.nodeid = ino; + out->body.entry.attr.mode = S_IFDIR | mode; + SET_OUT_HEADER_LEN(out, entry); + })); + + ASSERT_EQ(0, access(FULLPATH, F_OK)) << strerror(errno); +} + +TEST_F(Mkdir, ok) +{ + const char FULLPATH[] = "mountpoint/some_dir"; + const char RELPATH[] = "some_dir"; + mode_t mode = 0755; + uint64_t ino = 42; + + EXPECT_LOOKUP(RELPATH).WillOnce(Invoke(ReturnErrno(ENOENT))); + + EXPECT_CALL(*m_mock, process( + ResultOf([=](auto in) { + const char *name = (const char*)in->body.bytes + + sizeof(fuse_mkdir_in); + return (in->header.opcode == FUSE_MKDIR && + in->body.mkdir.mode == (S_IFDIR | mode) && + (0 == strcmp(RELPATH, name))); + }, Eq(true)), + _) + ).WillOnce(Invoke([=](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); +} Modified: projects/fuse2/tests/sys/fs/fuse/mockfs.hh ============================================================================== --- projects/fuse2/tests/sys/fs/fuse/mockfs.hh Tue Mar 5 18:52:13 2019 (r344811) +++ projects/fuse2/tests/sys/fs/fuse/mockfs.hh Tue Mar 5 18:53:28 2019 (r344812) @@ -67,11 +67,13 @@ struct fuse_create_out { }; union fuse_payloads_in { + fuse_access_in access; /* value is from fuse_kern_chan.c in fusefs-libs */ uint8_t bytes[0x21000 - sizeof(struct fuse_in_header)]; fuse_forget_in forget; fuse_init_in init; char lookup[0]; + fuse_mkdir_in mkdir; fuse_mknod_in mknod; fuse_open_in open; fuse_setattr_in setattr;