| // Copyright 2021 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. |
| |
| use { |
| crate::flags::Rights, fidl::endpoints::create_proxy, fidl_fuchsia_component as fcomponent, |
| fidl_fuchsia_component_decl as fdecl, fidl_fuchsia_io as fio, fidl_fuchsia_io_test as io_test, |
| fuchsia_zircon as zx, |
| }; |
| |
| /// Helper struct for connecting to an io1 test harness and running a conformance test on it. |
| pub struct TestHarness { |
| /// FIDL proxy to the io1 test harness. |
| pub proxy: io_test::Io1HarnessProxy, |
| |
| /// Config for the filesystem. |
| pub config: io_test::Io1Config, |
| |
| /// All [`io_test::Directory`] rights supported by the filesystem. |
| pub dir_rights: Rights, |
| |
| /// All [`io_test::File`] rights supported by the filesystem. |
| pub file_rights: Rights, |
| |
| /// All [`io_test::ExecutableFile`] rights supported by the filesystem. |
| pub executable_file_rights: Rights, |
| } |
| |
| impl TestHarness { |
| /// Connects to the test harness and returns a `TestHarness` struct. |
| pub async fn new() -> TestHarness { |
| let proxy = connect_to_harness().await; |
| let config = proxy.get_config().await.expect("Could not get config from proxy"); |
| |
| // Validate configuration options for consistency, disallow invalid combinations. |
| if config.supports_rename.unwrap_or_default() || config.supports_link.unwrap_or_default() { |
| assert!( |
| config.supports_get_token.unwrap_or_default(), |
| "GetToken must be supported for testing Rename/Link!" |
| ); |
| } |
| |
| // Generate set of supported open rights for each object type. |
| let dir_rights = Rights::new(get_supported_dir_rights(&config)); |
| let file_rights = |
| Rights::new(fio::OpenFlags::RIGHT_READABLE | fio::OpenFlags::RIGHT_WRITABLE); |
| let executable_file_rights = |
| Rights::new(fio::OpenFlags::RIGHT_READABLE | fio::OpenFlags::RIGHT_EXECUTABLE); |
| |
| TestHarness { proxy, config, dir_rights, file_rights, executable_file_rights } |
| } |
| |
| /// Creates a [`fio::DirectoryProxy`] with the given root directory structure. |
| pub fn get_directory( |
| &self, |
| root: io_test::Directory, |
| flags: fio::OpenFlags, |
| ) -> fio::DirectoryProxy { |
| let (client, server) = create_proxy::<fio::DirectoryMarker>().expect("Cannot create proxy"); |
| self.proxy |
| .get_directory(root, flags, server) |
| .expect("Cannot get directory from test harness"); |
| client |
| } |
| |
| /// Returns the abilities [`io_test::File`] objects should have for the harness. |
| pub fn supported_file_abilities(&self) -> fio::Abilities { |
| fio::Abilities::READ_BYTES |
| | fio::Abilities::WRITE_BYTES |
| | fio::Abilities::GET_ATTRIBUTES |
| | fio::Abilities::UPDATE_ATTRIBUTES |
| } |
| |
| /// Returns the abilities [`io_test::Directory`] objects should have for the harness. |
| pub fn supported_dir_abilities(&self) -> fio::Abilities { |
| fio::Abilities::GET_ATTRIBUTES |
| | fio::Abilities::UPDATE_ATTRIBUTES |
| | fio::Abilities::ENUMERATE |
| | fio::Abilities::TRAVERSE |
| | fio::Abilities::MODIFY_DIRECTORY |
| } |
| } |
| |
| async fn connect_to_harness() -> io_test::Io1HarnessProxy { |
| // Connect to the realm to get acccess to the outgoing directory for the harness. |
| let (client, server) = zx::Channel::create(); |
| fuchsia_component::client::connect_channel_to_protocol::<fcomponent::RealmMarker>(server) |
| .expect("Cannot connect to Realm service"); |
| let realm = fcomponent::RealmSynchronousProxy::new(client); |
| // fs_test is the name of the child component defined in the manifest. |
| let child_ref = fdecl::ChildRef { name: "fs_test".to_string(), collection: None }; |
| let (client, server) = zx::Channel::create(); |
| realm |
| .open_exposed_dir( |
| &child_ref, |
| fidl::endpoints::ServerEnd::<fio::DirectoryMarker>::new(server), |
| zx::Time::INFINITE, |
| ) |
| .expect("FIDL error when binding to child in Realm") |
| .expect("Cannot bind to test harness child in Realm"); |
| |
| let exposed_dir = fio::DirectoryProxy::new(fidl::AsyncChannel::from_channel(client)); |
| |
| fuchsia_component::client::connect_to_protocol_at_dir_root::<io_test::Io1HarnessMarker>( |
| &exposed_dir, |
| ) |
| .expect("Cannot connect to test harness protocol") |
| } |
| |
| /// Returns the aggregate of all io1 rights that are supported for [`io_test::Directory`] objects. |
| fn get_supported_dir_rights(config: &io_test::Io1Config) -> fio::OpenFlags { |
| fio::OpenFlags::RIGHT_READABLE |
| | fio::OpenFlags::RIGHT_WRITABLE |
| | if config.supports_executable_file.unwrap_or(false) { |
| fio::OpenFlags::RIGHT_EXECUTABLE |
| } else { |
| fio::OpenFlags::empty() |
| } |
| } |