blob: 47f07cd7b7a4275dea9e25421589495fba7eba1f [file] [log] [blame]
// Copyright 2019 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 {
anyhow::{Context as _, Error},
fidl::endpoints::{self, Proxy},
fidl_fidl_test_components as ftest, fidl_fuchsia_component as fcomponent,
fidl_fuchsia_io::{DirectoryMarker, DirectoryProxy, MODE_TYPE_SERVICE},
fidl_fuchsia_sys2 as fsys, fuchsia_async as fasync,
fuchsia_component::client,
io_util::{self, OPEN_RIGHT_READABLE},
std::path::PathBuf,
};
#[fasync::run_singlethreaded(test)]
async fn collections() {
let realm = client::connect_to_service::<fsys::RealmMarker>()
.expect("could not connect to Realm service");
// Create a couple child components.
for name in vec!["a", "b"] {
let mut collection_ref = fsys::CollectionRef { name: "coll".to_string() };
let child_decl = fsys::ChildDecl {
name: Some(name.to_string()),
url: Some(format!(
"fuchsia-pkg://fuchsia.com/collections_integration_test#meta/trigger_{}.cm",
name
)),
startup: Some(fsys::StartupMode::Lazy),
environment: None,
..fsys::ChildDecl::EMPTY
};
realm
.create_child(&mut collection_ref, child_decl)
.await
.expect(&format!("create_child {} failed", name))
.expect(&format!("failed to create child {}", name));
}
let children = list_children(&realm).await.expect("failed to list children");
assert_eq!("coll:a,coll:b", &children);
// Bind to children, causing them to execute.
for name in vec!["a", "b"] {
let mut child_ref = new_child_ref(name, "coll");
let (dir, server_end) = endpoints::create_proxy::<DirectoryMarker>().unwrap();
realm
.bind_child(&mut child_ref, server_end)
.await
.expect(&format!("bind_child {} failed", name))
.expect(&format!("failed to bind to child {}", name));
let trigger = open_trigger_svc(&dir).expect("failed to open trigger service");
let out = trigger.run().await.expect(&format!("trigger {} failed", name));
assert_eq!(out, format!("Triggered {}", name));
}
// Destroy one.
{
let mut child_ref = new_child_ref("a", "coll");
realm
.destroy_child(&mut child_ref)
.await
.expect("destroy_child a failed")
.expect("failed to destroy child");
}
// Binding to destroyed child should fail.
{
let (_, server_end) = endpoints::create_proxy::<DirectoryMarker>().unwrap();
let mut child_ref = new_child_ref("a", "coll");
let res =
realm.bind_child(&mut child_ref, server_end).await.expect("second bind_child a failed");
let err = res.expect_err("expected bind_child a to fail");
assert_eq!(err, fcomponent::Error::InstanceNotFound);
}
let children = list_children(&realm).await.expect("failed to list children");
assert_eq!("coll:b", &children);
// Recreate child (with different URL), and bind to it. Should work.
{
let mut collection_ref = fsys::CollectionRef { name: "coll".to_string() };
let child_decl = fsys::ChildDecl {
name: Some("a".to_string()),
url: Some(
"fuchsia-pkg://fuchsia.com/collections_integration_test#meta/trigger_realm.cm"
.to_string(),
),
startup: Some(fsys::StartupMode::Lazy),
environment: None,
..fsys::ChildDecl::EMPTY
};
realm
.create_child(&mut collection_ref, child_decl)
.await
.expect("second create_child a failed")
.expect("failed to create second child a");
}
{
let (dir, server_end) = endpoints::create_proxy::<DirectoryMarker>().unwrap();
let mut child_ref = new_child_ref("a", "coll");
realm
.bind_child(&mut child_ref, server_end)
.await
.expect("bind_child a failed")
.expect("failed to bind to child a");
let trigger = open_trigger_svc(&dir).expect("failed to open trigger service");
let out = trigger.run().await.expect("second trigger a failed");
assert_eq!(&out, "Triggered a");
}
let children = list_children(&realm).await.expect("failed to list children");
assert_eq!("coll:a,coll:b", &children);
}
fn new_child_ref(name: &str, collection: &str) -> fsys::ChildRef {
fsys::ChildRef { name: name.to_string(), collection: Some(collection.to_string()) }
}
async fn list_children(realm: &fsys::RealmProxy) -> Result<String, Error> {
let (iterator_proxy, server_end) = endpoints::create_proxy().unwrap();
let mut collection_ref = fsys::CollectionRef { name: "coll".to_string() };
realm
.list_children(&mut collection_ref, server_end)
.await
.expect("list_children failed")
.expect("failed to list children");
let res = iterator_proxy.next().await;
let children = res.expect("failed to iterate over children");
let children: Vec<_> = children
.iter()
.map(|c| format!("{}:{}", c.collection.as_ref().expect("no collection"), &c.name))
.collect();
Ok(children.join(","))
}
fn open_trigger_svc(dir: &DirectoryProxy) -> Result<ftest::TriggerProxy, Error> {
let node_proxy = io_util::open_node(
dir,
&PathBuf::from("fidl.test.components.Trigger"),
OPEN_RIGHT_READABLE,
MODE_TYPE_SERVICE,
)
.context("failed to open trigger service")?;
Ok(ftest::TriggerProxy::new(node_proxy.into_channel().unwrap()))
}