Home | History | Annotate | Download | only in tests
      1 /*
      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 
     24 #include <android-base/logging.h>
     25 #include <android-base/unique_fd.h>
     26 #include <gtest/gtest.h>
     27 
     28 namespace android {
     29 namespace fuse {
     30 namespace {
     31 
     32 class Callback : public FuseBridgeLoopCallback {
     33  public:
     34   bool mounted;
     35   bool closed;
     36   Callback() : mounted(false), closed(false) {}
     37 
     38   void OnMount(int /*mount_id*/) override { mounted = true; }
     39 
     40   void OnClosed(int /* mount_id */) override { closed = true; }
     41 };
     42 
     43 class FuseBridgeLoopTest : public ::testing::Test {
     44  protected:
     45   base::unique_fd dev_sockets_[2];
     46   base::unique_fd proxy_sockets_[2];
     47   Callback callback_;
     48   std::thread thread_;
     49 
     50   FuseRequest request_;
     51   FuseResponse response_;
     52 
     53   void SetUp() override {
     54     base::SetMinimumLogSeverity(base::VERBOSE);
     55     ASSERT_TRUE(SetupMessageSockets(&dev_sockets_));
     56     ASSERT_TRUE(SetupMessageSockets(&proxy_sockets_));
     57     thread_ = std::thread([this] {
     58         FuseBridgeLoop loop;
     59         loop.AddBridge(1, std::move(dev_sockets_[1]), std::move(proxy_sockets_[0]));
     60         loop.Start(&callback_);
     61     });
     62   }
     63 
     64   void CheckNotImpl(uint32_t opcode) {
     65     SCOPED_TRACE((std::ostringstream() << "opcode: " << opcode).str());
     66 
     67     memset(&request_, 0, sizeof(FuseRequest));
     68     request_.header.opcode = opcode;
     69     request_.header.len = sizeof(fuse_in_header);
     70     ASSERT_TRUE(request_.Write(dev_sockets_[0]));
     71 
     72     memset(&response_, 0, sizeof(FuseResponse));
     73     ASSERT_TRUE(response_.Read(dev_sockets_[0]));
     74     EXPECT_EQ(-ENOSYS, response_.header.error);
     75   }
     76 
     77   void CheckProxy(uint32_t opcode) {
     78     SCOPED_TRACE((std::ostringstream() << "opcode: " << opcode).str());
     79 
     80     memset(&request_, 0, sizeof(FuseRequest));
     81     request_.header.opcode = opcode;
     82     request_.header.unique = opcode; // Use opcode as unique.
     83     request_.header.len = sizeof(fuse_in_header);
     84     ASSERT_TRUE(request_.Write(dev_sockets_[0]));
     85 
     86     memset(&request_, 0, sizeof(FuseRequest));
     87     ASSERT_TRUE(request_.Read(proxy_sockets_[1]));
     88     EXPECT_EQ(opcode, request_.header.opcode);
     89     EXPECT_EQ(opcode, request_.header.unique);
     90 
     91     memset(&response_, 0, sizeof(FuseResponse));
     92     response_.header.len = sizeof(fuse_out_header);
     93     response_.header.unique = opcode;  // Use opcode as unique.
     94     response_.header.error = kFuseSuccess;
     95     ASSERT_TRUE(response_.Write(proxy_sockets_[1]));
     96 
     97     memset(&response_, 0, sizeof(FuseResponse));
     98     ASSERT_TRUE(response_.Read(dev_sockets_[0]));
     99     EXPECT_EQ(opcode, response_.header.unique);
    100     EXPECT_EQ(kFuseSuccess, response_.header.error);
    101   }
    102 
    103   void SendInitRequest(uint64_t unique) {
    104     memset(&request_, 0, sizeof(FuseRequest));
    105     request_.header.opcode = FUSE_INIT;
    106     request_.header.unique = unique;
    107     request_.header.len = sizeof(fuse_in_header) + sizeof(fuse_init_in);
    108     request_.init_in.major = FUSE_KERNEL_VERSION;
    109     request_.init_in.minor = FUSE_KERNEL_MINOR_VERSION;
    110     ASSERT_TRUE(request_.Write(dev_sockets_[0]));
    111   }
    112 
    113   void Close() {
    114     dev_sockets_[0].reset();
    115     dev_sockets_[1].reset();
    116     proxy_sockets_[0].reset();
    117     proxy_sockets_[1].reset();
    118     if (thread_.joinable()) {
    119       thread_.join();
    120     }
    121     ASSERT_TRUE(callback_.closed);
    122   }
    123 
    124   void TearDown() override {
    125     Close();
    126   }
    127 };
    128 
    129 } //  namespace
    130 
    131 TEST_F(FuseBridgeLoopTest, FuseInit) {
    132   SendInitRequest(1u);
    133 
    134   memset(&response_, 0, sizeof(FuseResponse));
    135   ASSERT_TRUE(response_.Read(dev_sockets_[0]));
    136   EXPECT_EQ(kFuseSuccess, response_.header.error);
    137   EXPECT_EQ(1u, response_.header.unique);
    138 
    139   // Unmount.
    140   Close();
    141   EXPECT_TRUE(callback_.mounted);
    142 }
    143 
    144 TEST_F(FuseBridgeLoopTest, FuseForget) {
    145   memset(&request_, 0, sizeof(FuseRequest));
    146   request_.header.opcode = FUSE_FORGET;
    147   request_.header.unique = 1u;
    148   request_.header.len = sizeof(fuse_in_header) + sizeof(fuse_forget_in);
    149   ASSERT_TRUE(request_.Write(dev_sockets_[0]));
    150 
    151   SendInitRequest(2u);
    152 
    153   memset(&response_, 0, sizeof(FuseResponse));
    154   ASSERT_TRUE(response_.Read(dev_sockets_[0]));
    155   EXPECT_EQ(2u, response_.header.unique) <<
    156       "The loop must not respond to FUSE_FORGET";
    157 }
    158 
    159 TEST_F(FuseBridgeLoopTest, FuseNotImpl) {
    160   CheckNotImpl(FUSE_SETATTR);
    161   CheckNotImpl(FUSE_READLINK);
    162   CheckNotImpl(FUSE_SYMLINK);
    163   CheckNotImpl(FUSE_MKNOD);
    164   CheckNotImpl(FUSE_MKDIR);
    165   CheckNotImpl(FUSE_UNLINK);
    166   CheckNotImpl(FUSE_RMDIR);
    167   CheckNotImpl(FUSE_RENAME);
    168   CheckNotImpl(FUSE_LINK);
    169   CheckNotImpl(FUSE_STATFS);
    170   CheckNotImpl(FUSE_SETXATTR);
    171   CheckNotImpl(FUSE_GETXATTR);
    172   CheckNotImpl(FUSE_LISTXATTR);
    173   CheckNotImpl(FUSE_REMOVEXATTR);
    174   CheckNotImpl(FUSE_FLUSH);
    175   CheckNotImpl(FUSE_OPENDIR);
    176   CheckNotImpl(FUSE_READDIR);
    177   CheckNotImpl(FUSE_RELEASEDIR);
    178   CheckNotImpl(FUSE_FSYNCDIR);
    179   CheckNotImpl(FUSE_GETLK);
    180   CheckNotImpl(FUSE_SETLK);
    181   CheckNotImpl(FUSE_SETLKW);
    182   CheckNotImpl(FUSE_ACCESS);
    183   CheckNotImpl(FUSE_CREATE);
    184   CheckNotImpl(FUSE_INTERRUPT);
    185   CheckNotImpl(FUSE_BMAP);
    186   CheckNotImpl(FUSE_DESTROY);
    187   CheckNotImpl(FUSE_IOCTL);
    188   CheckNotImpl(FUSE_POLL);
    189   CheckNotImpl(FUSE_NOTIFY_REPLY);
    190   CheckNotImpl(FUSE_BATCH_FORGET);
    191   CheckNotImpl(FUSE_FALLOCATE);
    192   CheckNotImpl(FUSE_READDIRPLUS);
    193   CheckNotImpl(FUSE_RENAME2);
    194   CheckNotImpl(FUSE_LSEEK);
    195 }
    196 
    197 TEST_F(FuseBridgeLoopTest, Proxy) {
    198   CheckProxy(FUSE_LOOKUP);
    199   CheckProxy(FUSE_GETATTR);
    200   CheckProxy(FUSE_READ);
    201   CheckProxy(FUSE_WRITE);
    202   CheckProxy(FUSE_FSYNC);
    203 
    204   // Invoke FUSE_OPEN and FUSE_RELEASE at last as the loop will exit when all files are closed.
    205   CheckProxy(FUSE_OPEN);
    206   CheckProxy(FUSE_RELEASE);
    207 
    208   // Ensure the loop exits.
    209   Close();
    210 }
    211 
    212 }  // namespace fuse
    213 }  // namespace android
    214