| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| library fuchsia.io.test; |
| |
| using fuchsia.mem; |
| using fuchsia.io; |
| using zx; |
| |
| // TODO(fxbug.dev/33880): Implement full testing framework. For now, we are |
| // hard-coding the desired directory layout manually in separate "Get" |
| // functions. In the next step, we would want to have a protocol to describe |
| // the intended directory layout setup, and integrate io2 connections. |
| |
| /// Conformance test harnesses will implement this protocol to setup its |
| /// associated filesystem servers with the described directory layout, |
| /// allowing their implementation of `fuchsia.io` and `fuchsia.io2` protocols |
| /// to be verified by a common test suite. |
| /// |
| /// Different test cases will not interact with one another during the |
| /// conformance test, and only one test case will be active at a time per |
| /// tested filesystem. So it is possible to host all cases as different |
| /// sub-directories under a common filesystem instance, to simplify the |
| /// lifecycle and implementation. |
| /// |
| /// If a test case has mutable bits, each method call should be implemented |
| /// to obtain the directory in its original state. In other words, repeated |
| /// test case set up should "as-if" yield new directories. |
| /// |
| /// See `src/storage/conformance/README.md` for an overview of io conformance |
| /// testing. |
| /// |
| /// `Io1Config` lets the test harness modulate the set of expected outcomes and |
| /// behaviors validated by the test suite, by declaring specific properties |
| /// about the filesystem implementation. For example, setting [`ImmutableFile`] |
| /// to true informs the test suites that files hosted by this harness do not |
| /// support mutation. |
| type Io1Config = table { |
| /// Files are read-only. |
| 1: immutable_file bool; |
| |
| /// Directories are read-only. |
| 2: immutable_dir bool; |
| |
| /// ExecFile objects are not supported. |
| 3: no_execfile bool; |
| |
| /// VmoFile objects are not supported. |
| 4: no_vmofile bool; |
| |
| /// Remote directories are not supported. |
| 5: no_remote_dir bool; |
| |
| /// The admin right is not supported. |
| 6: no_admin bool; |
| |
| /// The GetBuffer method is not supported. |
| 7: no_get_buffer bool; |
| |
| /// The Rename method is not supported. |
| 8: no_rename bool; |
| |
| /// The Link and Unlink methods are not supported. |
| 9: no_link bool; |
| |
| /// The SetAttr method is not supported. |
| 10: no_set_attr bool; |
| |
| /// The GetToken method is not supported. |
| 11: no_get_token bool; |
| |
| /// Path handling does not conform to in-tree behavior. |
| /// TODO(fxbug.dev/82672): Ensure all libraries are conformant and remove this option. |
| /// Currently the only non-conformant implementation being tested is the SDK VFS. |
| 12: non_conformant_path_handling bool; |
| }; |
| |
| /// Directory entries should support opening with any combination of read/write/execute rights. |
| /// If `no_admin` is false, the admin right should also be supported. |
| type Directory = resource table { |
| /// Name not required for root directory. |
| 1: name string; |
| |
| /// Nullable to sidestep recursion rules. Don't actually supply nulls. |
| 2: entries vector<DirectoryEntry:optional>; |
| }; |
| |
| /// File object which supports reading, and if `immutable_file` is false, also supports writing. |
| /// |
| /// As the conformance tests verify W^X enforcement, attempting to open a File object as executable |
| /// should fail with ACCESS_DENIED. If executable files are required, use ExecFile. |
| type File = table { |
| 1: name string; |
| 2: contents bytes; |
| }; |
| |
| /// Vmo-backed file object which supports opening as readable + writable. |
| /// |
| /// Enabled via the `no_vmofile` configuration option. |
| /// |
| /// As the conformance tests verify W^X enforcement, attempting to open a VmoFile as executable |
| /// should fail with ACCESS_DENIED. If executable pseudofiles are required, use ExecFile. |
| type VmoFile = resource table { |
| 1: name string; |
| 2: buffer fuchsia.mem.Range; |
| }; |
| |
| /// Adds an executable file that supports opening as readable + executable. The file has a non-zero |
| /// size, but the contents are otherwise unspecified. |
| /// |
| /// Enabled by setting `no_execfile` to false. If enabled, `no_get_buffer` should also be false. |
| /// |
| /// As the conformance tests verify W^X enforcement, attempting to open an ExecFile as writable |
| /// should fail with ACCESS_DENIED. If writable pseudofiles are required, use File/VmoFile instead. |
| type ExecutableFile = table { |
| 1: name string; |
| }; |
| |
| type DirectoryEntry = strict resource union { |
| 1: directory Directory; |
| 2: file File; |
| 3: vmo_file VmoFile; |
| 4: exec_file ExecutableFile; |
| }; |
| |
| @discoverable |
| protocol Io1Harness { |
| /// Returns the list of properties of the filesystem. |
| GetConfig() -> (struct { |
| config Io1Config; |
| }); |
| |
| /// Serves a directory with the given contents. |
| /// |
| /// `root` describes the initial layout of the filesystem that will be |
| /// used for the test case. The root directory that is served (returned via |
| /// `directory_request`) will have the equivalent contents, served with the |
| /// given `flags`. |
| GetDirectory(resource struct { |
| root Directory; |
| flags uint32; |
| directory_request server_end:fuchsia.io.Directory; |
| }); |
| |
| /// Serves a directory that holds a child `remote_directory` with name |
| /// `dir_name`. The `directory_request` connection to the root directory |
| /// has rights defined by `flags`. |
| /// |
| /// + `remote_directory` the client end of the child remote directory. |
| /// + `name` the name of the child remote directory in the root directory. |
| /// + `flags` the flags the served directory connection has. |
| /// + `directory_request` the server end of the root directory connection. |
| /// |
| /// TODO(fxbug.dev/33880): Add suppport for remote directories to |
| /// GetDirectory and then delete this method. |
| GetDirectoryWithRemoteDirectory(resource struct { |
| remote_directory client_end:fuchsia.io.Directory; |
| name string; |
| flags uint32; |
| directory_request server_end:fuchsia.io.Directory; |
| }); |
| }; |
| |
| /// Stub harness api for the io2.fidl protocol. |
| /// TODO(fxbug.dev/46082): Add separate io2 test harness api once we come up with a |
| /// good enough set of functions that we have enough flexibility to create |
| /// variable directory structures to with explicit permission settings for tests. |
| @discoverable |
| protocol Io2Harness { |
| /// Prepares a test case with an empty directory. The directory metadata |
| /// and directory entires should be read-only. |
| /// |
| /// + `directory_request` the server end of the root directory connection. |
| /// |
| /// This connection should have the following rights: |
| /// |
| /// * [`fuchsia.io2/Rights.CONNECT`]. |
| /// * [`fuchsia.io2/Rights.ENUMERATE`]. |
| /// * [`fuchsia.io2/Rights.TRAVERSE`]. |
| /// * [`fuchsia.io2/Rights.READ_BYTES`]. |
| /// * [`fuchsia.io2/Rights.WRITE_BYTES`]. |
| /// * [`fuchsia.io2/Rights.GET_ATTRIBUTES`]. |
| /// * [`fuchsia.io2/Rights.UPDATE_ATTRIBUTES`]. |
| /// |
| GetEmptyDirectory(resource struct { |
| directory_request zx.handle:CHANNEL; |
| }); |
| }; |