summaryrefslogtreecommitdiffhomepage
path: root/test/fuse/linux/fuse_base.h
diff options
context:
space:
mode:
Diffstat (limited to 'test/fuse/linux/fuse_base.h')
-rw-r--r--test/fuse/linux/fuse_base.h251
1 files changed, 0 insertions, 251 deletions
diff --git a/test/fuse/linux/fuse_base.h b/test/fuse/linux/fuse_base.h
deleted file mode 100644
index 6ad296ca2..000000000
--- a/test/fuse/linux/fuse_base.h
+++ /dev/null
@@ -1,251 +0,0 @@
-// Copyright 2020 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef GVISOR_TEST_FUSE_FUSE_BASE_H_
-#define GVISOR_TEST_FUSE_FUSE_BASE_H_
-
-#include <linux/fuse.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/uio.h>
-
-#include <iostream>
-#include <unordered_map>
-#include <vector>
-
-#include "gtest/gtest.h"
-#include "test/util/posix_error.h"
-#include "test/util/temp_path.h"
-
-namespace gvisor {
-namespace testing {
-
-constexpr char kMountOpts[] = "rootmode=755,user_id=0,group_id=0";
-
-constexpr struct fuse_init_out kDefaultFUSEInitOutPayload = {.major = 7};
-
-// Internal commands used to communicate between testing thread and the FUSE
-// server. See test/fuse/README.md for further detail.
-enum class FuseTestCmd {
- kSetResponse = 0,
- kSetInodeLookup,
- kGetRequest,
- kGetNumUnconsumedRequests,
- kGetNumUnsentResponses,
- kGetTotalReceivedBytes,
- kSkipRequest,
-};
-
-// Holds the information of a memory block in a serial buffer.
-struct FuseMemBlock {
- uint32_t opcode;
- size_t offset;
- size_t len;
-};
-
-// A wrapper of a simple serial buffer that can be used with read(2) and
-// write(2). Contains a cursor to indicate accessing. This class is not thread-
-// safe and can only be used in single-thread version.
-class FuseMemBuffer {
- public:
- FuseMemBuffer() : cursor_(0) {
- // To read from /dev/fuse, a buffer needs at least FUSE_MIN_READ_BUFFER
- // bytes to avoid EINVAL. FuseMemBuffer holds memory that can accommodate
- // a sequence of FUSE request/response, so it is initiated with double
- // minimal requirement.
- mem_.resize(FUSE_MIN_READ_BUFFER * 2);
- }
-
- // Returns whether there is no memory block.
- bool Empty() { return blocks_.empty(); }
-
- // Returns if there is no more remaining memory blocks.
- bool End() { return cursor_ == blocks_.size(); }
-
- // Returns how many bytes that have been received.
- size_t UsedBytes() {
- return Empty() ? 0 : blocks_.back().offset + blocks_.back().len;
- }
-
- // Returns the available bytes remains in the serial buffer.
- size_t AvailBytes() { return mem_.size() - UsedBytes(); }
-
- // Appends a memory block information that starts at the tail of the serial
- // buffer. /dev/fuse requires at least FUSE_MIN_READ_BUFFER bytes to read, or
- // it will issue EINVAL. If it is not enough, just double the buffer length.
- void AddMemBlock(uint32_t opcode, void* data, size_t len) {
- if (AvailBytes() < FUSE_MIN_READ_BUFFER) {
- mem_.resize(mem_.size() << 1);
- }
- size_t offset = UsedBytes();
- memcpy(mem_.data() + offset, data, len);
- blocks_.push_back(FuseMemBlock{opcode, offset, len});
- }
-
- // Returns the memory address at a specific offset. Used with read(2) or
- // write(2).
- char* DataAtOffset(size_t offset) { return mem_.data() + offset; }
-
- // Returns current memory block pointed by the cursor and increase by 1.
- FuseMemBlock Next() {
- if (End()) {
- std::cerr << "Buffer is already exhausted." << std::endl;
- return FuseMemBlock{};
- }
- return blocks_[cursor_++];
- }
-
- // Returns the number of the blocks that has not been requested.
- size_t RemainingBlocks() { return blocks_.size() - cursor_; }
-
- private:
- size_t cursor_;
- std::vector<FuseMemBlock> blocks_;
- std::vector<char> mem_;
-};
-
-// FuseTest base class is useful in FUSE integration test. Inherit this class
-// to automatically set up a fake FUSE server and use the member functions
-// to manipulate with it. Refer to test/fuse/README.md for detailed explanation.
-class FuseTest : public ::testing::Test {
- public:
- // nodeid_ is the ID of a fake inode. We starts from 2 since 1 is occupied by
- // the mount point.
- FuseTest() : nodeid_(2) {}
- void SetUp() override;
- void TearDown() override;
-
- // Called by the testing thread to set up a fake response for an expected
- // opcode via socket. This can be used multiple times to define a sequence of
- // expected FUSE reactions.
- void SetServerResponse(uint32_t opcode, std::vector<struct iovec>& iovecs);
-
- // Called by the testing thread to install a fake path under the mount point.
- // e.g. a file under /mnt/dir/file and moint point is /mnt, then it will look
- // up "dir/file" in this case.
- //
- // It sets a fixed response to the FUSE_LOOKUP requests issued with this
- // path, pretending there is an inode and avoid ENOENT when testing. If mode
- // is not given, it creates a regular file with mode 0600.
- void SetServerInodeLookup(const std::string& path,
- mode_t mode = S_IFREG | S_IRUSR | S_IWUSR,
- uint64_t size = 512);
-
- // Called by the testing thread to ask the FUSE server for its next received
- // FUSE request. Be sure to use the corresponding struct of iovec to receive
- // data from server.
- void GetServerActualRequest(std::vector<struct iovec>& iovecs);
-
- // Called by the testing thread to query the number of unconsumed requests in
- // the requests_ serial buffer of the FUSE server. TearDown() ensures all
- // FUSE requests received by the FUSE server were consumed by the testing
- // thread.
- uint32_t GetServerNumUnconsumedRequests();
-
- // Called by the testing thread to query the number of unsent responses in
- // the responses_ serial buffer of the FUSE server. TearDown() ensures all
- // preset FUSE responses were sent out by the FUSE server.
- uint32_t GetServerNumUnsentResponses();
-
- // Called by the testing thread to ask the FUSE server for its total received
- // bytes from /dev/fuse.
- uint32_t GetServerTotalReceivedBytes();
-
- // Called by the testing thread to ask the FUSE server to skip stored
- // request data.
- void SkipServerActualRequest();
-
- protected:
- TempPath mount_point_;
-
- // Opens /dev/fuse and inherit the file descriptor for the FUSE server.
- void MountFuse(const char* mountOpts = kMountOpts);
-
- // Creates a socketpair for communication and forks FUSE server.
- void SetUpFuseServer(
- const struct fuse_init_out* payload = &kDefaultFUSEInitOutPayload);
-
- // Unmounts the mountpoint of the FUSE server.
- void UnmountFuse();
-
- private:
- // Sends a FuseTestCmd and gets a uint32_t data from the FUSE server.
- inline uint32_t GetServerData(uint32_t cmd);
-
- // Waits for FUSE server to complete its processing. Complains if the FUSE
- // server responds any failure during tests.
- void WaitServerComplete();
-
- // The FUSE server stays here and waits next command or FUSE request until it
- // is terminated.
- void ServerFuseLoop();
-
- // Used by the FUSE server to tell testing thread if it is OK to proceed next
- // command. Will be issued after processing each FuseTestCmd.
- void ServerCompleteWith(bool success);
-
- // Consumes the first FUSE request when mounting FUSE. Replies with a
- // response with empty payload.
- PosixError ServerConsumeFuseInit(const struct fuse_init_out* payload);
-
- // A command switch that dispatch different FuseTestCmd to its handler.
- void ServerHandleCommand();
-
- // The FUSE server side's corresponding code of `SetServerResponse()`.
- // Handles `kSetResponse` command. Saves the fake response into its output
- // memory queue.
- void ServerReceiveResponse();
-
- // The FUSE server side's corresponding code of `SetServerInodeLookup()`.
- // Handles `kSetInodeLookup` command. Receives an expected file mode and
- // file path under the mount point.
- void ServerReceiveInodeLookup();
-
- // The FUSE server side's corresponding code of `GetServerActualRequest()`.
- // Handles `kGetRequest` command. Sends the next received request pointed by
- // the cursor.
- void ServerSendReceivedRequest();
-
- // Sends a uint32_t data via socket.
- inline void ServerSendData(uint32_t data);
-
- // The FUSE server side's corresponding code of `SkipServerActualRequest()`.
- // Handles `kSkipRequest` command. Skip the request pointed by current cursor.
- void ServerSkipReceivedRequest();
-
- // Handles FUSE request sent to /dev/fuse by its saved responses.
- void ServerProcessFuseRequest();
-
- // Responds to FUSE request with a saved data.
- void ServerRespondFuseSuccess(FuseMemBuffer& mem_buf,
- const FuseMemBlock& block, uint64_t unique);
-
- // Responds an error header to /dev/fuse when bad thing happens.
- void ServerRespondFuseError(uint64_t unique);
-
- int dev_fd_;
- int sock_[2];
-
- uint64_t nodeid_;
- std::unordered_map<std::string, FuseMemBlock> lookup_map_;
-
- FuseMemBuffer requests_;
- FuseMemBuffer responses_;
- FuseMemBuffer lookups_;
-};
-
-} // namespace testing
-} // namespace gvisor
-
-#endif // GVISOR_TEST_FUSE_FUSE_BASE_H_