diff options
Diffstat (limited to 'test/fuse')
-rw-r--r-- | test/fuse/README.md | 211 | ||||
-rw-r--r-- | test/fuse/linux/fuse_base.cc | 2 | ||||
-rw-r--r-- | test/fuse/linux/fuse_fd_util.cc | 1 | ||||
-rw-r--r-- | test/fuse/linux/readdir_test.cc | 15 |
4 files changed, 116 insertions, 113 deletions
diff --git a/test/fuse/README.md b/test/fuse/README.md index 7a1839714..65add57e2 100644 --- a/test/fuse/README.md +++ b/test/fuse/README.md @@ -14,8 +14,8 @@ server. It creates a `socketpair(2)` to send and receive control commands and data between the client and the server. Because the FUSE server runs in the background thread, gTest cannot catch its assertion failure immediately. Thus, `TearDown()` function sends command to the FUSE server to check if all gTest -assertion in the server are successful and all requests and preset responses -are consumed. +assertion in the server are successful and all requests and preset responses are +consumed. ## Communication Diagram @@ -29,80 +29,80 @@ however, it is still helpful to know when the client waits for the server to complete a command and when the server awaits the next instruction. ``` - | Client (Testing Thread) | Server (FUSE Server Thread) - | | - | >TEST_F() | - | >SetUp() | - | =MountFuse() | - | >SetUpFuseServer() | - | [create communication socket]| - | =fork() | =fork() - | [wait server complete] | - | | =ServerConsumeFuseInit() - | | =ServerCompleteWith() - | <SetUpFuseServer() | - | <SetUp() | - | [testing main] | - | | >ServerFuseLoop() - | | [poll on socket and fd] - | >SetServerResponse() | - | [write data to socket] | - | [wait server complete] | - | | [socket event occurs] - | | >ServerHandleCommand() - | | >ServerReceiveResponse() - | | [read data from socket] - | | [save data to memory] - | | <ServerReceiveResponse() - | | =ServerCompleteWith() - | <SetServerResponse() | - | | <ServerHandleCommand() - | >[Do fs operation] | - | [wait for fs response] | - | | [fd event occurs] - | | >ServerProcessFuseRequest() - | | =[read fs request] - | | =[save fs request to memory] - | | =[write fs response] - | <[Do fs operation] | - | | <ServerProcessFuseRequest() - | | - | =[Test fs operation result] | - | | - | >GetServerActualRequest() | - | [write data to socket] | - | [wait data from server] | - | | [socket event occurs] - | | >ServerHandleCommand() - | | >ServerSendReceivedRequest() - | | [write data to socket] - | [read data from socket] | - | [wait server complete] | - | | <ServerSendReceivedRequest() - | | =ServerCompleteWith() - | <GetServerActualRequest() | - | | <ServerHandleCommand() - | | - | =[Test actual request] | - | | - | >TearDown() | - | ... | - | >GetServerNumUnsentResponses() | - | [write data to socket] | - | [wait server complete] | - | | [socket event arrive] - | | >ServerHandleCommand() - | | >ServerSendData() - | | [write data to socket] - | | <ServerSendData() - | | =ServerCompleteWith() - | [read data from socket] | - | [test if all succeeded] | - | <GetServerNumUnsentResponses() | - | | <ServerHandleCommand() - | =UnmountFuse() | - | <TearDown() | - | <TEST_F() | +| Client (Testing Thread) | Server (FUSE Server Thread) +| | +| >TEST_F() | +| >SetUp() | +| =MountFuse() | +| >SetUpFuseServer() | +| [create communication socket]| +| =fork() | =fork() +| [wait server complete] | +| | =ServerConsumeFuseInit() +| | =ServerCompleteWith() +| <SetUpFuseServer() | +| <SetUp() | +| [testing main] | +| | >ServerFuseLoop() +| | [poll on socket and fd] +| >SetServerResponse() | +| [write data to socket] | +| [wait server complete] | +| | [socket event occurs] +| | >ServerHandleCommand() +| | >ServerReceiveResponse() +| | [read data from socket] +| | [save data to memory] +| | <ServerReceiveResponse() +| | =ServerCompleteWith() +| <SetServerResponse() | +| | <ServerHandleCommand() +| >[Do fs operation] | +| [wait for fs response] | +| | [fd event occurs] +| | >ServerProcessFuseRequest() +| | =[read fs request] +| | =[save fs request to memory] +| | =[write fs response] +| <[Do fs operation] | +| | <ServerProcessFuseRequest() +| | +| =[Test fs operation result] | +| | +| >GetServerActualRequest() | +| [write data to socket] | +| [wait data from server] | +| | [socket event occurs] +| | >ServerHandleCommand() +| | >ServerSendReceivedRequest() +| | [write data to socket] +| [read data from socket] | +| [wait server complete] | +| | <ServerSendReceivedRequest() +| | =ServerCompleteWith() +| <GetServerActualRequest() | +| | <ServerHandleCommand() +| | +| =[Test actual request] | +| | +| >TearDown() | +| ... | +| >GetServerNumUnsentResponses() | +| [write data to socket] | +| [wait server complete] | +| | [socket event arrive] +| | >ServerHandleCommand() +| | >ServerSendData() +| | [write data to socket] +| | <ServerSendData() +| | =ServerCompleteWith() +| [read data from socket] | +| [test if all succeeded] | +| <GetServerNumUnsentResponses() | +| | <ServerHandleCommand() +| =UnmountFuse() | +| <TearDown() | +| <TEST_F() | ``` ## Running the tests @@ -124,17 +124,18 @@ $ bazel test --test_tag_filters=fuse //test/fuse/... ## Writing a new FUSE test -1. Add test targets in `BUILD` and `linux/BUILD`. -2. Inherit your test from `FuseTest` base class. It allows you to: - - Fork a fake FUSE server in background during each test setup. - - Create a pair of sockets for communication and provide utility functions. - - Stop FUSE server and check if error occurs in it after test completes. -3. Build the expected opcode-response pairs of your FUSE operation. -4. Call `SetServerResponse()` to preset the next expected opcode and response. -5. Do real filesystem operations (FUSE is mounted at `mount_point_`). -6. Check FUSE response and/or errors. -7. Retrieve FUSE request by `GetServerActualRequest()`. -8. Check if the request is as expected. +1. Add test targets in `BUILD` and `linux/BUILD`. +2. Inherit your test from `FuseTest` base class. It allows you to: + - Fork a fake FUSE server in background during each test setup. + - Create a pair of sockets for communication and provide utility + functions. + - Stop FUSE server and check if error occurs in it after test completes. +3. Build the expected opcode-response pairs of your FUSE operation. +4. Call `SetServerResponse()` to preset the next expected opcode and response. +5. Do real filesystem operations (FUSE is mounted at `mount_point_`). +6. Check FUSE response and/or errors. +7. Retrieve FUSE request by `GetServerActualRequest()`. +8. Check if the request is as expected. A few customized matchers used in syscalls test are encouraged to test the outcome of filesystem operations. Such as: @@ -158,11 +159,12 @@ FUSE server in response to a sequence of FUSE requests. The lifecycle of a command contains following steps: -1. The testing thread sends a `FuseTestCmd` via socket and waits for completion. -2. The FUSE server receives the command and does corresponding action. -3. (Optional) The testing thread reads data from socket. -4. The FUSE server sends a success indicator via socket after processing. -5. The testing thread gets the success signal and continues testing. +1. The testing thread sends a `FuseTestCmd` via socket and waits for + completion. +2. The FUSE server receives the command and does corresponding action. +3. (Optional) The testing thread reads data from socket. +4. The FUSE server sends a success indicator via socket after processing. +5. The testing thread gets the success signal and continues testing. The success indicator, i.e. `WaitServerComplete()`, is crucial at the end of each `FuseTestCmd` sent from the testing thread. Because we don't want to begin @@ -172,16 +174,15 @@ supported now. To add a new `FuseTestCmd`, one must comply with following format: -1. Add a new `FuseTestCmd` enum class item defined in `linux/fuse_base.h` -2. Add a `SetServerXXX()` or `GetServerXXX()` public function in `FuseTest`. - This is how the testing thread will call to send control message. Define how - many bytes you want to send along with the command and what you will expect - to receive. Finally it should block and wait for a success indicator from - the FUSE server. -3. Add a handler logic in the switch condition of `ServerHandleCommand()`. Use - `ServerSendData()` or declare a new private function such as - `ServerReceiveXXX()` or `ServerSendXXX()`. It is mandatory to set it private - since only the FUSE server (forked from `FuseTest` base class) can call it. - This is the server part of the specific `FuseTestCmd` and the format of the - data should be consistent with what the client expects in the previous step. - +1. Add a new `FuseTestCmd` enum class item defined in `linux/fuse_base.h` +2. Add a `SetServerXXX()` or `GetServerXXX()` public function in `FuseTest`. + This is how the testing thread will call to send control message. Define how + many bytes you want to send along with the command and what you will expect + to receive. Finally it should block and wait for a success indicator from + the FUSE server. +3. Add a handler logic in the switch condition of `ServerHandleCommand()`. Use + `ServerSendData()` or declare a new private function such as + `ServerReceiveXXX()` or `ServerSendXXX()`. It is mandatory to set it private + since only the FUSE server (forked from `FuseTest` base class) can call it. + This is the server part of the specific `FuseTestCmd` and the format of the + data should be consistent with what the client expects in the previous step. diff --git a/test/fuse/linux/fuse_base.cc b/test/fuse/linux/fuse_base.cc index a033db117..5b45804e1 100644 --- a/test/fuse/linux/fuse_base.cc +++ b/test/fuse/linux/fuse_base.cc @@ -24,8 +24,8 @@ #include <sys/uio.h> #include <unistd.h> -#include "absl/strings/str_format.h" #include "gtest/gtest.h" +#include "absl/strings/str_format.h" #include "test/util/fuse_util.h" #include "test/util/posix_error.h" #include "test/util/temp_path.h" diff --git a/test/fuse/linux/fuse_fd_util.cc b/test/fuse/linux/fuse_fd_util.cc index 4a2505b00..30d1157bb 100644 --- a/test/fuse/linux/fuse_fd_util.cc +++ b/test/fuse/linux/fuse_fd_util.cc @@ -59,4 +59,3 @@ Cleanup FuseFdTest::CloseFD(FileDescriptor &fd) { } // namespace testing } // namespace gvisor - diff --git a/test/fuse/linux/readdir_test.cc b/test/fuse/linux/readdir_test.cc index ab61eb676..2afb4b062 100644 --- a/test/fuse/linux/readdir_test.cc +++ b/test/fuse/linux/readdir_test.cc @@ -127,8 +127,9 @@ TEST_F(ReaddirTest, SingleEntry) { char *readdir_payload = readdir_payload_vec.data(); // Use fake ino for other directories. - fill_fuse_dirent(readdir_payload, dot.c_str(), ino_dir-2); - fill_fuse_dirent(readdir_payload + dot_file_dirent_size, dot_dot.c_str(), ino_dir-1); + fill_fuse_dirent(readdir_payload, dot.c_str(), ino_dir - 2); + fill_fuse_dirent(readdir_payload + dot_file_dirent_size, dot_dot.c_str(), + ino_dir - 1); fill_fuse_dirent( readdir_payload + dot_file_dirent_size + dot_dot_file_dirent_size, test_file.c_str(), ino_dir); @@ -148,8 +149,9 @@ TEST_F(ReaddirTest, SingleEntry) { std::vector<char> buf(4090, 0); int nread, off = 0, i = 0; - EXPECT_THAT(nread = syscall(__NR_getdents64, fd.get(), buf.data(), buf.size()), - SyscallSucceeds()); + EXPECT_THAT( + nread = syscall(__NR_getdents64, fd.get(), buf.data(), buf.size()), + SyscallSucceeds()); for (; off < nread;) { struct dirent64 *ent = (struct dirent64 *)(buf.data() + off); off += ent->d_reclen; @@ -166,8 +168,9 @@ TEST_F(ReaddirTest, SingleEntry) { } } - EXPECT_THAT(nread = syscall(__NR_getdents64, fd.get(), buf.data(), buf.size()), - SyscallSucceedsWithValue(0)); + EXPECT_THAT( + nread = syscall(__NR_getdents64, fd.get(), buf.data(), buf.size()), + SyscallSucceedsWithValue(0)); SkipServerActualRequest(); // READDIR. SkipServerActualRequest(); // READDIR with no data. |