| // 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::{Context as _, Error}, |
| async_trait::async_trait, |
| component_events::{ |
| events::{Destroyed, Event}, |
| injectors::{CapabilityInjector as _, ProtocolInjector}, |
| matcher::EventMatcher, |
| sequence::{EventSequence, Ordering}, |
| }, |
| fidl_fuchsia_component_client_test::{EmptyProtocolMarker, EmptyProtocolRequestStream}, |
| fuchsia_async as fasync, fuchsia_syslog as syslog, |
| futures::{SinkExt as _, StreamExt as _}, |
| log::info, |
| std::sync::Arc, |
| test_case::test_case, |
| test_utils_lib::opaque_test::OpaqueTest, |
| }; |
| |
| struct PassthroughInjector { |
| sender: futures::channel::mpsc::Sender<EmptyProtocolRequestStream>, |
| } |
| |
| #[async_trait] |
| impl ProtocolInjector for PassthroughInjector { |
| type Marker = EmptyProtocolMarker; |
| |
| async fn serve( |
| self: Arc<Self>, |
| request_stream: EmptyProtocolRequestStream, |
| ) -> Result<(), Error> { |
| self.sender.clone().send(request_stream).await.context("failed to send request stream") |
| } |
| } |
| |
| #[test_case("fuchsia-pkg://fuchsia.com/fuchsia-component-tests#meta/realm_with_wait.cm"; "wait")] |
| #[test_case("fuchsia-pkg://fuchsia.com/fuchsia-component-tests#meta/realm.cm"; "no_wait")] |
| #[fasync::run_singlethreaded(test)] |
| async fn scoped_instances(root_component: &'static str) -> Result<(), Error> { |
| syslog::init_with_tags(&["fuchsia_component_v2_test"]).expect("could not initialize logging"); |
| let test = OpaqueTest::default(root_component).await?; |
| |
| let mut event_source = test.connect_to_event_source().await?; |
| let event = EventMatcher::ok().r#type(Destroyed::TYPE).moniker("./coll:auto-*".to_string()); |
| let mut expected_events: Vec<_> = (0..3).map(|_| event.clone()).collect(); |
| expected_events |
| .push(EventMatcher::ok().r#type(Destroyed::TYPE).moniker("./coll:static_name".to_string())); |
| let expectation = EventSequence::new() |
| .all_of(expected_events, Ordering::Unordered) |
| .subscribe_and_expect(&mut event_source) |
| .await?; |
| |
| let (sender, mut receiver) = futures::channel::mpsc::channel(1); |
| let injector = Arc::new(PassthroughInjector { sender }); |
| let () = injector.inject(&event_source, EventMatcher::ok()).await; |
| |
| let () = event_source.start_component_tree().await; |
| |
| // The realm component will connect to our injected capability once it's done with its work. |
| // Wait for that to happen before matching on event expectations. |
| info!("Waiting for test component to signal ready"); |
| let mut request_stream = |
| receiver.next().await.context("failed to observe capability request")?; |
| |
| info!("Waiting for scoped instances to be destroyed"); |
| let () = expectation.await?; |
| |
| drop(test); |
| // Prove connection to the component under test is severed after dropping everything. |
| match request_stream.next().await { |
| Some(r) => panic!("unexpected item from request stream: {:?}", r), |
| None => (), |
| } |
| |
| Ok(()) |
| } |