gvisor/test/fuse
gVisor bot e6df6222ac Merge pull request #3250 from craig08:fuse-getattr
PiperOrigin-RevId: 326313858
2020-08-12 14:36:04 -07:00
..
linux Merge pull request #3250 from craig08:fuse-getattr 2020-08-12 14:36:04 -07:00
BUILD Implement FUSE_GETATTR 2020-08-10 18:15:32 -07:00
README.md Merge pull request #3320 from craig08:fuse-integration-test 2020-08-04 13:25:40 -07:00

README.md

gVisor FUSE Test Suite

This is an integration test suite for fuse(4) filesystem. It runs under both gVisor and Linux, and ensures compatibility between the two. This test suite is based on system calls test.

This document describes the framework of fuse integration test and the guidelines that should be followed when adding new fuse tests.

Integration Test Framework

Please refer to the figure below. > is entering the function, < is leaving the function, and = indicates sequentially entering and leaving.

 |  Client (Test Main Process)         |  Server (FUSE Daemon)
 |                                     |
 |  >TEST_F()                          |
 |    >SetUp()                         |
 |      =MountFuse()                   |
 |      >SetUpFuseServer()             |
 |        [create communication pipes] |
 |        =fork()                      |        =fork()
 |        >WaitCompleted()             |
 |          [wait for MarkDone()]      |
 |                                     |        =ConsumeFuseInit()
 |                                     |        =MarkDone()
 |        <WaitCompleted()             |
 |      <SetUpFuseServer()             |
 |    <SetUp()                         |
 |    >SetExpected()                   |
 |      [construct expected reaction]  |
 |                                     |        >FuseLoop()
 |                                     |          >ReceiveExpected()
 |                                     |            [wait data from pipe]
 |      [write data to pipe]           |
 |      [wait for MarkDone()]          |
 |                                     |            [save data to memory]
 |                                     |            =MarkDone()
 |    <SetExpected()                   |
 |                                     |          <ReceiveExpected()
 |                                     |          >read()
 |                                     |            [wait for fs operation]
 |    >[Do fs operation]               |
 |      [wait for fs response]         |
 |                                     |          <read()
 |                                     |          =CompareRequest()
 |                                     |          =write() [write fs response]
 |    <[Do fs operation]               |
 |    =[Test fs operation result]      |
 |    =[wait for MarkDone()]           |
 |                                     |          =MarkDone()
 |    >TearDown()                      |
 |      =UnmountFuse()                 |
 |    <TearDown()                      |
 |  <TEST_F()                          |

Running the tests

Based on syscall tests, fuse tests can run in different environments. To enable fuse testing environment, the test targets should be appended with _fuse.

For example, to run fuse test in stat_test.cc:

$ bazel test //test/fuse:stat_test_runsc_ptrace_vfs2_fuse

Test all targets tagged with fuse:

$ 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:
    • Run a fake FUSE server in background during each test setup.
    • Create pipes for communication and provide utility functions.
    • Stop FUSE server after test completes.
  3. Customize your comparison function for request assessment in FUSE server.
  4. Add the mapping of the size of structs if you are working on new FUSE opcode.
    • Please update FuseTest::GetPayloadSize() for each new FUSE opcode.
  5. Build the expected request-response pair of your FUSE operation.
  6. Call SetExpected() function to inject the expected reaction.
  7. Check the response and/or errors.
  8. Finally call WaitCompleted() to ensure the FUSE server acts correctly.

A few customized matchers used in syscalls test are encouraged to test the outcome of filesystem operations. Such as:

SyscallSucceeds()
SyscallSucceedsWithValue(...)
SyscallFails()
SyscallFailsWithErrno(...)

Please refer to test/syscalls/README.md for further details.