]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tests/sys/fs/fusefs/open.cc
fusefs: adapt the tests to the fuse => fusefs rename
[FreeBSD/FreeBSD.git] / tests / sys / fs / fusefs / open.cc
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2019 The FreeBSD Foundation
5  *
6  * This software was developed by BFF Storage Systems, LLC under sponsorship
7  * from the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 extern "C" {
32 #include <fcntl.h>
33 }
34
35 #include "mockfs.hh"
36 #include "utils.hh"
37
38 using namespace testing;
39
40 class Open: public FuseTest {
41
42 public:
43
44 /* Test an OK open of a file with the given flags */
45 void test_ok(int os_flags, int fuse_flags) {
46         const char FULLPATH[] = "mountpoint/some_file.txt";
47         const char RELPATH[] = "some_file.txt";
48         uint64_t ino = 42;
49         int fd;
50
51         FuseTest::expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1);
52         EXPECT_CALL(*m_mock, process(
53                 ResultOf([=](auto in) {
54                         return (in->header.opcode == FUSE_OPEN &&
55                                 in->body.open.flags == (uint32_t)fuse_flags &&
56                                 in->header.nodeid == ino);
57                 }, Eq(true)),
58                 _)
59         ).WillOnce(Invoke(ReturnImmediate([](auto in __unused, auto out) {
60                 out->header.len = sizeof(out->header);
61                 SET_OUT_HEADER_LEN(out, open);
62         })));
63
64         /* Until the attr cache is working, we may send an additional GETATTR */
65         EXPECT_CALL(*m_mock, process(
66                 ResultOf([=](auto in) {
67                         return (in->header.opcode == FUSE_GETATTR &&
68                                 in->header.nodeid == ino);
69                 }, Eq(true)),
70                 _)
71         ).WillRepeatedly(Invoke(ReturnImmediate([=](auto i __unused, auto out) {
72                 SET_OUT_HEADER_LEN(out, attr);
73                 out->body.attr.attr.ino = ino;  // Must match nodeid
74                 out->body.attr.attr.mode = S_IFREG | 0644;
75         })));
76
77         fd = open(FULLPATH, os_flags);
78         EXPECT_LE(0, fd) << strerror(errno);
79         /* Deliberately leak fd.  close(2) will be tested in release.cc */
80 }
81 };
82
83
84 /* 
85  * The fuse daemon fails the request with enoent.  This usually indicates a
86  * race condition: some other FUSE client removed the file in between when the
87  * kernel checked for it with lookup and tried to open it
88  */
89 TEST_F(Open, enoent)
90 {
91         const char FULLPATH[] = "mountpoint/some_file.txt";
92         const char RELPATH[] = "some_file.txt";
93         uint64_t ino = 42;
94
95         expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1);
96         EXPECT_CALL(*m_mock, process(
97                 ResultOf([=](auto in) {
98                         return (in->header.opcode == FUSE_OPEN &&
99                                 in->header.nodeid == ino);
100                 }, Eq(true)),
101                 _)
102         ).WillOnce(Invoke(ReturnErrno(ENOENT)));
103         EXPECT_NE(0, open(FULLPATH, O_RDONLY));
104         EXPECT_EQ(ENOENT, errno);
105 }
106
107 /* 
108  * The daemon is responsible for checking file permissions (unless the
109  * default_permissions mount option was used)
110  */
111 TEST_F(Open, eperm)
112 {
113         const char FULLPATH[] = "mountpoint/some_file.txt";
114         const char RELPATH[] = "some_file.txt";
115         uint64_t ino = 42;
116
117         expect_lookup(RELPATH, ino, S_IFREG | 0644, 0, 1);
118         EXPECT_CALL(*m_mock, process(
119                 ResultOf([=](auto in) {
120                         return (in->header.opcode == FUSE_OPEN &&
121                                 in->header.nodeid == ino);
122                 }, Eq(true)),
123                 _)
124         ).WillOnce(Invoke(ReturnErrno(EPERM)));
125         EXPECT_NE(0, open(FULLPATH, O_RDONLY));
126         EXPECT_EQ(EPERM, errno);
127 }
128
129 /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236340 */
130 TEST_F(Open, DISABLED_o_append)
131 {
132         test_ok(O_WRONLY | O_APPEND, O_WRONLY | O_APPEND);
133 }
134
135 /* The kernel is supposed to filter out this flag */
136 TEST_F(Open, o_creat)
137 {
138         test_ok(O_WRONLY | O_CREAT, O_WRONLY);
139 }
140
141 /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236340 */
142 TEST_F(Open, DISABLED_o_direct)
143 {
144         test_ok(O_WRONLY | O_DIRECT, O_WRONLY | O_DIRECT);
145 }
146
147 /* The kernel is supposed to filter out this flag */
148 TEST_F(Open, o_excl)
149 {
150         test_ok(O_WRONLY | O_EXCL, O_WRONLY);
151 }
152
153 /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236329 */
154 TEST_F(Open, DISABLED_o_exec)
155 {
156         test_ok(O_EXEC, O_EXEC);
157 }
158
159 /* The kernel is supposed to filter out this flag */
160 TEST_F(Open, o_noctty)
161 {
162         test_ok(O_WRONLY | O_NOCTTY, O_WRONLY);
163 }
164
165 TEST_F(Open, o_rdonly)
166 {
167         test_ok(O_RDONLY, O_RDONLY);
168 }
169
170 /* https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236340 */
171 TEST_F(Open, DISABLED_o_trunc)
172 {
173         test_ok(O_WRONLY | O_TRUNC, O_WRONLY | O_TRUNC);
174 }
175
176 TEST_F(Open, o_wronly)
177 {
178         test_ok(O_WRONLY, O_WRONLY);
179 }
180
181 TEST_F(Open, o_rdwr)
182 {
183         test_ok(O_RDWR, O_RDWR);
184 }
185