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     request_.header.unique = 1;
     71     ASSERT_TRUE(request_.Write(dev_sockets_[0]));
     72 
     73     memset(&response_, 0, sizeof(FuseResponse));
     74     ASSERT_TRUE(response_.Read(dev_sockets_[0]));
     75     EXPECT_EQ(-ENOSYS, response_.header.error);
     76   }
     77 
     78   void CheckProxy(uint32_t opcode) {
     79     SCOPED_TRACE((std::ostringstream() << "opcode: " << opcode).str());
     80 
     81     memset(&request_, 0, sizeof(FuseRequest));
     82     request_.header.opcode = opcode;
     83     request_.header.unique = opcode; // Use opcode as unique.
     84     request_.header.len = sizeof(fuse_in_header);
     85     ASSERT_TRUE(request_.Write(dev_sockets_[0]));
     86 
     87     memset(&request_, 0, sizeof(FuseRequest));
     88     ASSERT_TRUE(request_.Read(proxy_sockets_[1]));
     89     EXPECT_EQ(opcode, request_.header.opcode);
     90     EXPECT_EQ(opcode, request_.header.unique);
     91 
     92     memset(&response_, 0, sizeof(FuseResponse));
     93     response_.header.len = sizeof(fuse_out_header);
     94     response_.header.unique = opcode;  // Use opcode as unique.
     95     response_.header.error = kFuseSuccess;
     96     ASSERT_TRUE(response_.Write(proxy_sockets_[1]));
     97 
     98     memset(&response_, 0, sizeof(FuseResponse));
     99     ASSERT_TRUE(response_.Read(dev_sockets_[0]));
    100     EXPECT_EQ(opcode, response_.header.unique);
    101     EXPECT_EQ(kFuseSuccess, response_.header.error);
    102   }
    103 
    104   void SendInitRequest(uint64_t unique) {
    105     memset(&request_, 0, sizeof(FuseRequest));
    106     request_.header.opcode = FUSE_INIT;
    107     request_.header.unique = unique;
    108     request_.header.len = sizeof(fuse_in_header) + sizeof(fuse_init_in);
    109     request_.init_in.major = FUSE_KERNEL_VERSION;
    110     request_.init_in.minor = FUSE_KERNEL_MINOR_VERSION;
    111     ASSERT_TRUE(request_.Write(dev_sockets_[0]));
    112   }
    113 
    114   void Close() {
    115     dev_sockets_[0].reset();
    116     dev_sockets_[1].reset();
    117     proxy_sockets_[0].reset();
    118     proxy_sockets_[1].reset();
    119     if (thread_.joinable()) {
    120       thread_.join();
    121     }
    122     ASSERT_TRUE(callback_.closed);
    123   }
    124 
    125   void TearDown() override {
    126     Close();
    127   }
    128 };
    129 
    130 } //  namespace
    131 
    132 TEST_F(FuseBridgeLoopTest, FuseInit) {
    133   SendInitRequest(1u);
    134 
    135   memset(&response_, 0, sizeof(FuseResponse));
    136   ASSERT_TRUE(response_.Read(dev_sockets_[0]));
    137   EXPECT_EQ(kFuseSuccess, response_.header.error);
    138   EXPECT_EQ(1u, response_.header.unique);
    139 
    140   // Unmount.
    141   Close();
    142   EXPECT_TRUE(callback_.mounted);
    143 }
    144 
    145 TEST_F(FuseBridgeLoopTest, FuseForget) {
    146   memset(&request_, 0, sizeof(FuseRequest));
    147   request_.header.opcode = FUSE_FORGET;
    148   request_.header.unique = 1u;
    149   request_.header.len = sizeof(fuse_in_header) + sizeof(fuse_forget_in);
    150   ASSERT_TRUE(request_.Write(dev_sockets_[0]));
    151 
    152   SendInitRequest(2u);
    153 
    154   memset(&response_, 0, sizeof(FuseResponse));
    155   ASSERT_TRUE(response_.Read(dev_sockets_[0]));
    156   EXPECT_EQ(2u, response_.header.unique) <<
    157       "The loop must not respond to FUSE_FORGET";
    158 }
    159 
    160 TEST_F(FuseBridgeLoopTest, FuseNotImpl) {
    161   CheckNotImpl(FUSE_SETATTR);
    162   CheckNotImpl(FUSE_READLINK);
    163   CheckNotImpl(FUSE_SYMLINK);
    164   CheckNotImpl(FUSE_MKNOD);
    165   CheckNotImpl(FUSE_MKDIR);
    166   CheckNotImpl(FUSE_UNLINK);
    167   CheckNotImpl(FUSE_RMDIR);
    168   CheckNotImpl(FUSE_RENAME);
    169   CheckNotImpl(FUSE_LINK);
    170   CheckNotImpl(FUSE_STATFS);
    171   CheckNotImpl(FUSE_SETXATTR);
    172   CheckNotImpl(FUSE_GETXATTR);
    173   CheckNotImpl(FUSE_LISTXATTR);
    174   CheckNotImpl(FUSE_REMOVEXATTR);
    175   CheckNotImpl(FUSE_FLUSH);
    176   CheckNotImpl(FUSE_OPENDIR);
    177   CheckNotImpl(FUSE_READDIR);
    178   CheckNotImpl(FUSE_RELEASEDIR);
    179   CheckNotImpl(FUSE_FSYNCDIR);
    180   CheckNotImpl(FUSE_GETLK);
    181   CheckNotImpl(FUSE_SETLK);
    182   CheckNotImpl(FUSE_SETLKW);
    183   CheckNotImpl(FUSE_ACCESS);
    184   CheckNotImpl(FUSE_CREATE);
    185   CheckNotImpl(FUSE_INTERRUPT);
    186   CheckNotImpl(FUSE_BMAP);
    187   CheckNotImpl(FUSE_DESTROY);
    188   CheckNotImpl(FUSE_IOCTL);
    189   CheckNotImpl(FUSE_POLL);
    190   CheckNotImpl(FUSE_NOTIFY_REPLY);
    191   CheckNotImpl(FUSE_BATCH_FORGET);
    192   CheckNotImpl(FUSE_FALLOCATE);
    193   CheckNotImpl(FUSE_READDIRPLUS);
    194   CheckNotImpl(FUSE_RENAME2);
    195   CheckNotImpl(FUSE_LSEEK);
    196 }
    197 
    198 TEST_F(FuseBridgeLoopTest, Proxy) {
    199   CheckProxy(FUSE_LOOKUP);
    200   CheckProxy(FUSE_GETATTR);
    201   CheckProxy(FUSE_READ);
    202   CheckProxy(FUSE_WRITE);
    203   CheckProxy(FUSE_FSYNC);
    204 
    205   // Invoke FUSE_OPEN and FUSE_RELEASE at last as the loop will exit when all files are closed.
    206   CheckProxy(FUSE_OPEN);
    207   CheckProxy(FUSE_RELEASE);
    208 
    209   // Ensure the loop exits.
    210   Close();
    211 }
    212 
    213 }  // namespace fuse
    214 }  // namespace android
    215