| // 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. |
| |
| // [START import_statement_rust] |
| use { |
| // [START_EXCLUDE] |
| anyhow::{Context, Error}, |
| fidl_fidl_examples_routing_echo as fecho, |
| fuchsia_component::server as fserver, |
| // [END_EXCLUDE] |
| fuchsia_component_test::{ |
| Capability, ChildOptions, LocalComponentHandles, RealmBuilder, Ref, Route, |
| }, |
| futures::{StreamExt, TryStreamExt}, |
| }; |
| // [END import_statement_rust] |
| |
| // This test demonstrates constructing a realm with two child components |
| // and verifying the `fidl.examples.routing.Echo` protocol. |
| #[fuchsia::test] |
| async fn routes_from_echo() -> Result<(), Error> { |
| // [START init_realm_builder_rust] |
| let builder = RealmBuilder::new().await?; |
| // [END init_realm_builder_rust] |
| |
| // [START add_component_rust] |
| // [START add_server_rust] |
| // Add component to the realm, which is fetched using a URL. |
| let echo_server = builder |
| .add_child( |
| "echo_server", |
| "fuchsia-pkg://fuchsia.com/realm-builder-examples#meta/echo_server.cm", |
| ChildOptions::new(), |
| ) |
| .await?; |
| // [END add_server_rust] |
| // Add component to the realm, which is fetched using a fragment-only URL. |
| // The child is not exposing a service, so the `eager` option ensures the |
| // child starts when the realm is built. |
| // This client is not used a part of the test, but is used to demonstrate |
| // routing between two children and is referenced in documentation. The test instead accesses |
| // the `fidl.examples.routing.echo.Echo` protocol from the test component as routed in |
| // route_to_test_rust below. |
| let echo_client = builder |
| .add_child("echo_client", "#meta/echo_client.cm", ChildOptions::new().eager()) |
| .await?; |
| // [END add_component_rust] |
| |
| // [START route_between_children_rust] |
| builder |
| .add_route( |
| Route::new() |
| .capability(Capability::protocol_by_name("fidl.examples.routing.echo.Echo")) |
| .from(&echo_server) |
| .to(&echo_client), |
| ) |
| .await?; |
| // [END route_between_children_rust] |
| |
| // [START route_to_test_rust] |
| builder |
| .add_route( |
| Route::new() |
| .capability(Capability::protocol_by_name("fidl.examples.routing.echo.Echo")) |
| .from(&echo_server) |
| .to(Ref::parent()), |
| ) |
| .await?; |
| // [END route_to_test_rust] |
| |
| // [START route_from_test_rust] |
| builder |
| .add_route( |
| Route::new() |
| .capability(Capability::protocol_by_name("fuchsia.logger.LogSink")) |
| .from(Ref::parent()) |
| .to(&echo_server) |
| .to(&echo_client), |
| ) |
| .await?; |
| // [END route_from_test_rust] |
| |
| // [START build_realm_rust] |
| let realm = builder.build().await?; |
| // [END build_realm_rust] |
| |
| // [START get_child_name_rust] |
| println!("Child Name: {}", realm.root.child_name()); |
| // [END get_child_name_rust] |
| |
| // [START call_echo_rust] |
| let echo: fecho::EchoProxy = realm.root.connect_to_protocol_at_exposed_dir()?; |
| assert_eq!(echo.echo_string(Some("hello")).await?, Some("hello".to_owned())); |
| // [END call_echo_rust] |
| |
| Ok(()) |
| } |
| |
| pub enum IncomingService { |
| Echo(fecho::EchoRequestStream), |
| } |
| |
| // [START mock_component_impl_rust] |
| async fn echo_server_mock(handles: LocalComponentHandles) -> Result<(), Error> { |
| // Create a new ServiceFs to host FIDL protocols from |
| let mut fs = fserver::ServiceFs::new(); |
| |
| // Add the echo protocol to the ServiceFs |
| fs.dir("svc").add_fidl_service(IncomingService::Echo); |
| |
| // Run the ServiceFs on the outgoing directory handle from the mock handles |
| fs.serve_connection(handles.outgoing_dir)?; |
| |
| fs.for_each_concurrent(0, move |IncomingService::Echo(stream)| async move { |
| stream |
| .map(|result| result.context("Request came with error")) |
| .try_for_each(|request| async move { |
| match request { |
| fecho::EchoRequest::EchoString { value, responder } => { |
| responder |
| .send(value.as_ref().map(|s| &**s)) |
| .expect("failed to send echo response"); |
| } |
| } |
| Ok(()) |
| }) |
| .await |
| .context("Failed to serve request stream") |
| .unwrap_or_else(|e| eprintln!("Error encountered: {:?}", e)) |
| }) |
| .await; |
| |
| Ok(()) |
| } |
| // [END mock_component_impl_rust] |
| |
| // This test demonstrates constructing a realm with a mocked LocalComponent |
| // implementation of the `fidl.examples.routing.Echo` protocol. |
| #[fuchsia::test] |
| async fn routes_from_mock_echo() -> Result<(), Error> { |
| let builder = RealmBuilder::new().await?; |
| |
| // [START add_mock_component_rust] |
| let echo_server = builder |
| .add_local_child( |
| "echo_server", |
| move |handles: LocalComponentHandles| Box::pin(echo_server_mock(handles)), |
| ChildOptions::new(), |
| ) |
| .await?; |
| // [END add_mock_component_rust] |
| |
| builder |
| .add_route( |
| Route::new() |
| .capability(Capability::protocol_by_name("fuchsia.logger.LogSink")) |
| .from(Ref::parent()) |
| .to(&echo_server), |
| ) |
| .await?; |
| |
| builder |
| .add_route( |
| Route::new() |
| .capability(Capability::protocol_by_name("fidl.examples.routing.echo.Echo")) |
| .from(&echo_server) |
| .to(Ref::parent()), |
| ) |
| .await?; |
| |
| let realm = builder.build().await?; |
| |
| let echo: fecho::EchoProxy = realm.root.connect_to_protocol_at_exposed_dir()?; |
| assert_eq!(echo.echo_string(Some("hello")).await?, Some("hello".to_owned())); |
| |
| Ok(()) |
| } |