blob: a15d22cfbc912262099b5a2f648109e9a8c9bb3a [file] [log] [blame]
// 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()
}
}