blob: a01e681fe8e8a41c26ba20cafbf85eb9c6707bbe [file] [log] [blame]
// 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.
use {
anyhow::Error,
fidl_fidl_examples_routing_echo as fecho, fuchsia_async as fasync,
fuchsia_component::client::{self as component, ScopedInstance},
fuchsia_syslog as syslog,
log::*,
regex::Regex,
std::{collections::BTreeSet, convert::TryFrom, iter::FromIterator},
test_utils_lib::events::{
CapabilityReady, Event, EventSource, MarkedForDestruction, Running, Started,
},
};
#[fasync::run_singlethreaded]
async fn main() -> Result<(), Error> {
syslog::init_with_tags(&[]).unwrap();
let mut instances = vec![];
let url =
"fuchsia-pkg://fuchsia.com/events_integration_test#meta/stub_component.cm".to_string();
let url_cap_ready =
"fuchsia-pkg://fuchsia.com/events_integration_test#meta/capability_ready_child.cm"
.to_string();
let scoped_instance = ScopedInstance::new("coll".to_string(), url_cap_ready.clone()).await?;
instances.push(scoped_instance);
for _ in 0..3 {
let scoped_instance = ScopedInstance::new("coll".to_string(), url.clone()).await?;
instances.push(scoped_instance);
}
// Destroy one instance, this shouldn't appear anywhere in the events.
let mut instance = instances.pop().unwrap();
let destroy_waiter = instance.take_destroy_waiter();
drop(instance);
destroy_waiter.await;
// Subscribe to events.
let event_source = EventSource::new_async()?;
let mut event_stream = event_source
.subscribe(vec![
Started::NAME,
Running::NAME,
MarkedForDestruction::NAME,
CapabilityReady::NAME,
])
.await?;
let echo = component::connect_to_service::<fecho::EchoMarker>()?;
// There were 4 running instances when the stream was created: this instance itself and three
// more. We are also expecting capability ready for one of them.
let mut running = vec![];
let mut capability_ready = BTreeSet::new();
while running.len() < 4 || capability_ready.len() < 1 {
let event = event_stream.next().await?;
match event.event_type {
Some(Running::TYPE) => {
let event = Running::try_from(event).expect("convert to running");
info!("Got running event");
running.push(event.target_moniker().to_string());
}
Some(CapabilityReady::TYPE) => {
let event = CapabilityReady::try_from(event).expect("convert to capability ready");
info!("Got capability ready event");
capability_ready.insert(event.target_moniker().to_string());
}
other => panic!("unexpected event type: {:?}", other),
}
}
for _ in &running {
let _ = echo.echo_string(Some(&format!("{:?}", Running::TYPE))).await?;
}
for _ in &capability_ready {
let _ = echo.echo_string(Some(&format!("{:?}", CapabilityReady::TYPE))).await?;
}
assert_eq!(running.len(), 4);
assert_eq!(capability_ready.len(), 1);
assert_eq!(running[0], ".");
let re = Regex::new(r"./coll:auto-\d+:\d").unwrap();
assert!(running[1..].iter().all(|m| re.is_match(m)));
assert_eq!(BTreeSet::from_iter::<Vec<String>>(running).len(), 4);
// Dropping instances stops and destroys the children.
drop(instances);
// The three instances were marked for destruction.
let mut seen_marked_for_destruction = 0;
while seen_marked_for_destruction != 3 {
let event = event_stream.next().await?;
match event.event_type {
Some(CapabilityReady::TYPE) => {
// ignore. we could get a duplicate here.
}
Some(MarkedForDestruction::TYPE) => {
let _ =
echo.echo_string(Some(&format!("{:?}", MarkedForDestruction::TYPE))).await?;
seen_marked_for_destruction += 1;
}
event => {
panic!("Got unexpected event type: {:?}", event);
}
}
}
Ok(())
}