use fidl::endpoints::ServerEnd;
use {
fidl_fuchsia_component as fcomponent, fidl_fuchsia_component_decl as fdecl,
fidl_fuchsia_io as fio,
};
pub async fn create_child_component(
child_name: &str,
child_url: &str,
collection_name: &str,
create_child_args: fcomponent::CreateChildArgs,
realm: &fcomponent::RealmProxy,
) -> Result<(), fcomponent::Error> {
let collection_ref = fdecl::CollectionRef { name: collection_name.to_string() };
let child_decl = fdecl::Child {
name: Some(child_name.to_string()),
url: Some(child_url.to_string()),
startup: Some(fdecl::StartupMode::Lazy),
environment: None,
..Default::default()
};
realm
.create_child(&collection_ref, &child_decl, create_child_args)
.await
.map_err(|_| fcomponent::Error::Internal)?
}
pub async fn open_child_component_exposed_dir(
child_name: &str,
collection_name: &str,
realm: &fcomponent::RealmProxy,
exposed_dir: ServerEnd<fio::DirectoryMarker>,
) -> Result<(), fcomponent::Error> {
let child_ref = fdecl::ChildRef {
name: child_name.to_string(),
collection: Some(collection_name.to_string()),
};
realm
.open_exposed_dir(&child_ref, exposed_dir)
.await
.map_err(|_| fcomponent::Error::Internal)?
}
pub async fn destroy_child_component(
child_name: &str,
collection_name: &str,
realm: &fcomponent::RealmProxy,
) -> Result<(), fcomponent::Error> {
let child_ref = fdecl::ChildRef {
name: child_name.to_string(),
collection: Some(collection_name.to_string()),
};
realm.destroy_child(&child_ref).await.map_err(|_| fcomponent::Error::Internal)?
}
#[cfg(test)]
mod tests {
use super::{
create_child_component, destroy_child_component, open_child_component_exposed_dir,
};
use fidl::endpoints::{create_endpoints, create_proxy, spawn_stream_handler};
use lazy_static::lazy_static;
use session_testing::spawn_directory_server;
use test_util::Counter;
use {fidl_fuchsia_component as fcomponent, fidl_fuchsia_io as fio};
#[fuchsia::test]
async fn create_child_parameters() {
let child_name = "test_child";
let child_url = "test_url";
let child_collection = "test_collection";
let realm_proxy = spawn_stream_handler(move |realm_request| async move {
match realm_request {
fcomponent::RealmRequest::CreateChild { collection, decl, args: _, responder } => {
assert_eq!(decl.name.unwrap(), child_name);
assert_eq!(decl.url.unwrap(), child_url);
assert_eq!(&collection.name, child_collection);
let _ = responder.send(Ok(()));
}
_ => panic!("Realm handler received an unexpected request"),
}
});
assert!(create_child_component(
child_name,
child_url,
child_collection,
Default::default(),
&realm_proxy
)
.await
.is_ok());
}
#[fuchsia::test]
async fn create_child_success() {
let realm_proxy = spawn_stream_handler(move |realm_request| async move {
match realm_request {
fcomponent::RealmRequest::CreateChild {
collection: _,
decl: _,
args: _,
responder,
} => {
let _ = responder.send(Ok(()));
}
_ => panic!("Realm handler received an unexpected request"),
}
});
assert!(create_child_component("", "", "", Default::default(), &realm_proxy).await.is_ok());
}
#[fuchsia::test]
async fn create_child_error() {
let realm_proxy = spawn_stream_handler(move |realm_request| async move {
match realm_request {
fcomponent::RealmRequest::CreateChild {
collection: _,
decl: _,
args: _,
responder,
} => {
let _ = responder.send(Err(fcomponent::Error::Internal));
}
_ => panic!("Realm handler received an unexpected request"),
}
});
assert!(create_child_component("", "", "", Default::default(), &realm_proxy)
.await
.is_err());
}
#[fuchsia::test]
async fn open_child_component_exposed_dir_parameters() {
let child_name = "test_child";
let child_collection = "test_collection";
let realm_proxy = spawn_stream_handler(move |realm_request| async move {
match realm_request {
fcomponent::RealmRequest::OpenExposedDir { child, exposed_dir: _, responder } => {
assert_eq!(child.name, child_name);
assert_eq!(child.collection, Some(child_collection.to_string()));
let _ = responder.send(Ok(()));
}
_ => panic!("Realm handler received an unexpected request"),
}
});
let (_exposed_dir, exposed_dir_server_end) = create_endpoints::<fio::DirectoryMarker>();
assert!(open_child_component_exposed_dir(
child_name,
child_collection,
&realm_proxy,
exposed_dir_server_end
)
.await
.is_ok());
}
#[fuchsia::test]
async fn open_child_component_exposed_dir_success() {
let realm_proxy = spawn_stream_handler(move |realm_request| async move {
match realm_request {
fcomponent::RealmRequest::OpenExposedDir {
child: _,
exposed_dir: _,
responder,
} => {
let _ = responder.send(Ok(()));
}
_ => panic!("Realm handler received an unexpected request"),
}
});
let (_exposed_dir, exposed_dir_server_end) = create_endpoints::<fio::DirectoryMarker>();
assert!(open_child_component_exposed_dir("", "", &realm_proxy, exposed_dir_server_end)
.await
.is_ok());
}
#[fuchsia::test]
async fn open_child_exposed_dir_success() {
lazy_static! {
static ref CALL_COUNT: Counter = Counter::new(0);
}
let directory_request_handler = |directory_request| match directory_request {
fio::DirectoryRequest::Open { path: fake_capability_path, .. } => {
CALL_COUNT.inc();
assert_eq!(fake_capability_path, "fake_capability_path");
}
_ => panic!("Directory handler received an unexpected request"),
};
let realm_proxy = spawn_stream_handler(move |realm_request| async move {
match realm_request {
fcomponent::RealmRequest::OpenExposedDir { child: _, exposed_dir, responder } => {
CALL_COUNT.inc();
spawn_directory_server(exposed_dir, directory_request_handler);
let _ = responder.send(Ok(()));
}
_ => panic!("Realm handler received an unexpected request"),
}
});
let (exposed_dir, exposed_dir_server_end) = create_endpoints::<fio::DirectoryMarker>();
open_child_component_exposed_dir("", "", &realm_proxy, exposed_dir_server_end)
.await
.unwrap();
let (proxy, server_end) = create_proxy::<fio::DirectoryMarker>();
assert!(fdio::service_connect_at(
&exposed_dir.into_channel(),
"fake_capability_path",
server_end.into_channel()
)
.is_ok());
assert!(proxy.rewind().await.is_err());
assert_eq!(CALL_COUNT.get(), 2);
}
#[fuchsia::test]
async fn open_child_component_exposed_dir_error() {
let realm_proxy = spawn_stream_handler(move |realm_request| async move {
match realm_request {
fcomponent::RealmRequest::OpenExposedDir {
child: _,
exposed_dir: _,
responder,
} => {
let _ = responder.send(Err(fcomponent::Error::Internal));
}
_ => panic!("Realm handler received an unexpected request"),
}
});
let (_exposed_dir, exposed_dir_server_end) = create_endpoints::<fio::DirectoryMarker>();
assert!(open_child_component_exposed_dir("", "", &realm_proxy, exposed_dir_server_end)
.await
.is_err());
}
#[fuchsia::test]
async fn destroy_child_parameters() {
let child_name = "test_child";
let child_collection = "test_collection";
let realm_proxy = spawn_stream_handler(move |realm_request| async move {
match realm_request {
fcomponent::RealmRequest::DestroyChild { child, responder } => {
assert_eq!(child.name, child_name);
assert_eq!(child.collection, Some(child_collection.to_string()));
let _ = responder.send(Ok(()));
}
_ => panic!("Realm handler received an unexpected request"),
}
});
assert!(destroy_child_component(child_name, child_collection, &realm_proxy).await.is_ok());
}
}