blob: b4c1efb01934677e674a1bee6d19c2485dced299 [file] [log] [blame]
Daichi Hironoc6134762016-10-27 14:57:55 +09001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specic language governing permissions and
14 * limitations under the License.
15 */
16
17#include "libappfuse/FuseBridgeLoop.h"
18
19#include <sys/socket.h>
20
21#include <sstream>
22#include <thread>
23
Daichi Hironoa0aecda2016-11-08 10:17:51 +090024#include <android-base/logging.h>
25#include <android-base/unique_fd.h>
Daichi Hironoc6134762016-10-27 14:57:55 +090026#include <gtest/gtest.h>
27
28namespace android {
Daichi Hironoa0aecda2016-11-08 10:17:51 +090029namespace fuse {
30namespace {
Daichi Hironoc6134762016-10-27 14:57:55 +090031
Daichi Hironoa0aecda2016-11-08 10:17:51 +090032class Callback : public FuseBridgeLoopCallback {
Daichi Hironoc6134762016-10-27 14:57:55 +090033 public:
34 bool mounted;
35 Callback() : mounted(false) {}
36 void OnMount() override {
37 mounted = true;
38 }
39};
40
41class FuseBridgeLoopTest : public ::testing::Test {
42 protected:
Daichi Hironoa0aecda2016-11-08 10:17:51 +090043 base::unique_fd dev_sockets_[2];
44 base::unique_fd proxy_sockets_[2];
Daichi Hironoc6134762016-10-27 14:57:55 +090045 Callback callback_;
46 std::thread thread_;
47
48 FuseRequest request_;
49 FuseResponse response_;
50
Daichi Hironoa0aecda2016-11-08 10:17:51 +090051 void SetUp() override {
52 base::SetMinimumLogSeverity(base::VERBOSE);
Daichi Hirono57b780f2017-03-06 14:02:42 +090053 ASSERT_TRUE(SetupMessageSockets(&dev_sockets_));
54 ASSERT_TRUE(SetupMessageSockets(&proxy_sockets_));
Daichi Hironoc6134762016-10-27 14:57:55 +090055 thread_ = std::thread([this] {
Daichi Hironoa0aecda2016-11-08 10:17:51 +090056 StartFuseBridgeLoop(
57 dev_sockets_[1].release(), proxy_sockets_[0].release(), &callback_);
Daichi Hironoc6134762016-10-27 14:57:55 +090058 });
59 }
60
61 void CheckNotImpl(uint32_t opcode) {
62 SCOPED_TRACE((std::ostringstream() << "opcode: " << opcode).str());
63
64 memset(&request_, 0, sizeof(FuseRequest));
65 request_.header.opcode = opcode;
66 request_.header.len = sizeof(fuse_in_header);
67 ASSERT_TRUE(request_.Write(dev_sockets_[0]));
68
69 memset(&response_, 0, sizeof(FuseResponse));
70 ASSERT_TRUE(response_.Read(dev_sockets_[0]));
71 EXPECT_EQ(-ENOSYS, response_.header.error);
72 }
73
74 void CheckProxy(uint32_t opcode) {
75 SCOPED_TRACE((std::ostringstream() << "opcode: " << opcode).str());
76
77 memset(&request_, 0, sizeof(FuseRequest));
78 request_.header.opcode = opcode;
79 request_.header.unique = opcode; // Use opcode as unique.
80 request_.header.len = sizeof(fuse_in_header);
81 ASSERT_TRUE(request_.Write(dev_sockets_[0]));
82
83 memset(&request_, 0, sizeof(FuseRequest));
84 ASSERT_TRUE(request_.Read(proxy_sockets_[1]));
85 EXPECT_EQ(opcode, request_.header.opcode);
86 EXPECT_EQ(opcode, request_.header.unique);
87
88 memset(&response_, 0, sizeof(FuseResponse));
89 response_.header.len = sizeof(fuse_out_header);
90 response_.header.unique = opcode; // Use opcode as unique.
91 response_.header.error = kFuseSuccess;
92 ASSERT_TRUE(response_.Write(proxy_sockets_[1]));
93
94 memset(&response_, 0, sizeof(FuseResponse));
95 ASSERT_TRUE(response_.Read(dev_sockets_[0]));
96 EXPECT_EQ(opcode, response_.header.unique);
97 EXPECT_EQ(kFuseSuccess, response_.header.error);
98 }
99
100 void SendInitRequest(uint64_t unique) {
101 memset(&request_, 0, sizeof(FuseRequest));
102 request_.header.opcode = FUSE_INIT;
103 request_.header.unique = unique;
104 request_.header.len = sizeof(fuse_in_header) + sizeof(fuse_init_in);
105 request_.init_in.major = FUSE_KERNEL_VERSION;
106 request_.init_in.minor = FUSE_KERNEL_MINOR_VERSION;
107 ASSERT_TRUE(request_.Write(dev_sockets_[0]));
108 }
109
110 void Close() {
Daichi Hironoa0aecda2016-11-08 10:17:51 +0900111 dev_sockets_[0].reset();
112 dev_sockets_[1].reset();
113 proxy_sockets_[0].reset();
114 proxy_sockets_[1].reset();
Daichi Hironoc6134762016-10-27 14:57:55 +0900115 if (thread_.joinable()) {
116 thread_.join();
117 }
118 }
119
Daichi Hironoa0aecda2016-11-08 10:17:51 +0900120 void TearDown() override {
Daichi Hironoc6134762016-10-27 14:57:55 +0900121 Close();
122 }
123};
124
Daichi Hironoa0aecda2016-11-08 10:17:51 +0900125} // namespace
126
Daichi Hironoc6134762016-10-27 14:57:55 +0900127TEST_F(FuseBridgeLoopTest, FuseInit) {
128 SendInitRequest(1u);
129
130 memset(&response_, 0, sizeof(FuseResponse));
131 ASSERT_TRUE(response_.Read(dev_sockets_[0]));
132 EXPECT_EQ(kFuseSuccess, response_.header.error);
133 EXPECT_EQ(1u, response_.header.unique);
134
135 // Unmount.
136 Close();
137 EXPECT_TRUE(callback_.mounted);
138}
139
140TEST_F(FuseBridgeLoopTest, FuseForget) {
141 memset(&request_, 0, sizeof(FuseRequest));
142 request_.header.opcode = FUSE_FORGET;
143 request_.header.unique = 1u;
144 request_.header.len = sizeof(fuse_in_header) + sizeof(fuse_forget_in);
145 ASSERT_TRUE(request_.Write(dev_sockets_[0]));
146
147 SendInitRequest(2u);
148
149 memset(&response_, 0, sizeof(FuseResponse));
150 ASSERT_TRUE(response_.Read(dev_sockets_[0]));
151 EXPECT_EQ(2u, response_.header.unique) <<
152 "The loop must not respond to FUSE_FORGET";
153}
154
155TEST_F(FuseBridgeLoopTest, FuseNotImpl) {
156 CheckNotImpl(FUSE_SETATTR);
157 CheckNotImpl(FUSE_READLINK);
158 CheckNotImpl(FUSE_SYMLINK);
159 CheckNotImpl(FUSE_MKNOD);
160 CheckNotImpl(FUSE_MKDIR);
161 CheckNotImpl(FUSE_UNLINK);
162 CheckNotImpl(FUSE_RMDIR);
163 CheckNotImpl(FUSE_RENAME);
164 CheckNotImpl(FUSE_LINK);
165 CheckNotImpl(FUSE_STATFS);
Daichi Hironoc6134762016-10-27 14:57:55 +0900166 CheckNotImpl(FUSE_SETXATTR);
167 CheckNotImpl(FUSE_GETXATTR);
168 CheckNotImpl(FUSE_LISTXATTR);
169 CheckNotImpl(FUSE_REMOVEXATTR);
Daichi Hironoa0aecda2016-11-08 10:17:51 +0900170 CheckNotImpl(FUSE_FLUSH);
Daichi Hironoc6134762016-10-27 14:57:55 +0900171 CheckNotImpl(FUSE_OPENDIR);
172 CheckNotImpl(FUSE_READDIR);
173 CheckNotImpl(FUSE_RELEASEDIR);
174 CheckNotImpl(FUSE_FSYNCDIR);
175 CheckNotImpl(FUSE_GETLK);
176 CheckNotImpl(FUSE_SETLK);
177 CheckNotImpl(FUSE_SETLKW);
178 CheckNotImpl(FUSE_ACCESS);
179 CheckNotImpl(FUSE_CREATE);
180 CheckNotImpl(FUSE_INTERRUPT);
181 CheckNotImpl(FUSE_BMAP);
182 CheckNotImpl(FUSE_DESTROY);
183 CheckNotImpl(FUSE_IOCTL);
184 CheckNotImpl(FUSE_POLL);
185 CheckNotImpl(FUSE_NOTIFY_REPLY);
186 CheckNotImpl(FUSE_BATCH_FORGET);
187 CheckNotImpl(FUSE_FALLOCATE);
188 CheckNotImpl(FUSE_READDIRPLUS);
189 CheckNotImpl(FUSE_RENAME2);
190 CheckNotImpl(FUSE_LSEEK);
191}
192
193TEST_F(FuseBridgeLoopTest, Proxy) {
194 CheckProxy(FUSE_LOOKUP);
195 CheckProxy(FUSE_GETATTR);
Daichi Hironoc6134762016-10-27 14:57:55 +0900196 CheckProxy(FUSE_READ);
197 CheckProxy(FUSE_WRITE);
Daichi Hironoa0aecda2016-11-08 10:17:51 +0900198 CheckProxy(FUSE_FSYNC);
Daichi Hirono30e68082016-11-15 09:31:21 +0900199
200 // Invoke FUSE_OPEN and FUSE_RELEASE at last as the loop will exit when all files are closed.
201 CheckProxy(FUSE_OPEN);
202 CheckProxy(FUSE_RELEASE);
203
204 // Ensure the loop exits.
205 Close();
Daichi Hironoc6134762016-10-27 14:57:55 +0900206}
207
Daichi Hironoa0aecda2016-11-08 10:17:51 +0900208} // namespace fuse
209} // namespace android