1// Copyright 2023 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
45use anyhow::{bail, Result};
6use fidl::endpoints::{
7 create_endpoints, ClientEnd, DiscoverableProtocolMarker, ServerEnd, ServiceMarker, ServiceProxy,
8};
9use fidl_fuchsia_io as fio;
10use fidl_fuchsia_testing_harness::{RealmProxy_Marker, RealmProxy_Proxy};
11use fuchsia_component::client::connect_to_protocol;
1213pub mod error;
14pub use error::Error;
1516// RealmProxyClient is a client for fuchsia.testing.harness.RealmProxy.
17//
18// The calling component must have a handle to the RealmProxy protocol in
19// order to use this struct. Once the caller has connected to the RealmProxy
20// service, they can access the other services in the proxied test realm by
21// calling [connect_to_protocol].
22//
23// # Example Usage
24//
25// ```
26// let realm_proxy = RealmProxyClient::connect()?;
27// let echo = realm_proxy.connect_to_protocol::<EchoMarker>().await?;
28// ```
29pub struct RealmProxyClient {
30 inner: RealmProxy_Proxy,
31}
3233impl From<RealmProxy_Proxy> for RealmProxyClient {
34fn from(value: RealmProxy_Proxy) -> Self {
35Self { inner: value }
36 }
37}
3839impl From<ClientEnd<RealmProxy_Marker>> for RealmProxyClient {
40fn from(value: ClientEnd<RealmProxy_Marker>) -> Self {
41let inner = value.into_proxy();
42Self { inner }
43 }
44}
4546impl RealmProxyClient {
47// Connects to the RealmProxy service.
48pub fn connect() -> Result<Self, anyhow::Error> {
49let inner = connect_to_protocol::<RealmProxy_Marker>()?;
50Ok(Self { inner })
51 }
5253// Connects to the protocol marked by [T] via the proxy.
54 //
55 // Returns an error if the connection fails.
56pub async fn connect_to_protocol<T: DiscoverableProtocolMarker>(
57&self,
58 ) -> Result<T::Proxy, anyhow::Error> {
59self.connect_to_named_protocol::<T>(T::PROTOCOL_NAME).await
60}
6162// Connects the `sever_end` to the protocol marked by [T] via the proxy.
63 //
64 // Returns an error if the connection fails.
65pub async fn connect_server_end_to_protocol<T: DiscoverableProtocolMarker>(
66&self,
67 server_end: ServerEnd<T>,
68 ) -> Result<(), anyhow::Error> {
69self.connect_server_end_to_named_protocol::<T>(T::PROTOCOL_NAME, server_end).await
70}
7172// Connects to the protocol with the given name, via the proxy.
73 //
74 // Returns an error if the connection fails.
75pub async fn connect_to_named_protocol<T: DiscoverableProtocolMarker>(
76&self,
77 protocol_name: &str,
78 ) -> Result<T::Proxy, anyhow::Error> {
79let (client, server) = create_endpoints::<T>();
80self.connect_server_end_to_named_protocol(protocol_name, server).await?;
81Ok(client.into_proxy())
82 }
8384// Connects the `server_end` to the protocol with the given name, via the proxy.
85 //
86 // Returns an error if the connection fails.
87pub async fn connect_server_end_to_named_protocol<T: DiscoverableProtocolMarker>(
88&self,
89 protocol_name: &str,
90 server_end: ServerEnd<T>,
91 ) -> Result<(), anyhow::Error> {
92let res =
93self.inner.connect_to_named_protocol(protocol_name, server_end.into_channel()).await?;
9495if let Some(op_err) = res.err() {
96bail!("{:?}", op_err);
97 }
9899Ok(())
100 }
101102// Opens the given service capability, via the proxy.
103 //
104 // See https://fuchsia.dev/fuchsia-src/concepts/components/v2/capabilities/service
105 // for more information about service capabilities.
106 //
107 // Returns an error if the connection fails.
108pub async fn open_service<T: ServiceMarker>(
109&self,
110 ) -> Result<fio::DirectoryProxy, anyhow::Error> {
111let (client, server) = create_endpoints::<fio::DirectoryMarker>();
112let res = self.inner.open_service(T::SERVICE_NAME, server.into_channel()).await?;
113if let Some(op_err) = res.err() {
114bail!("{:?}", op_err);
115 }
116117Ok(client.into_proxy())
118 }
119120// Connects to the given service instance, via the proxy.
121 //
122 // See https://fuchsia.dev/fuchsia-src/concepts/components/v2/capabilities/service
123 // for more information about service capabilities.
124 //
125 // Returns an error if the connection fails.
126pub async fn connect_to_service_instance<T: ServiceMarker>(
127&self,
128 instance: &str,
129 ) -> Result<T::Proxy, anyhow::Error> {
130let (client, server) = create_endpoints::<fio::DirectoryMarker>();
131let res = self
132.inner
133 .connect_to_service_instance(T::SERVICE_NAME, instance, server.into_channel())
134 .await?;
135if let Some(op_err) = res.err() {
136bail!("{:?}", op_err);
137 }
138139Ok(T::Proxy::from_member_opener(Box::new(
140 fuchsia_component::client::ServiceInstanceDirectory(
141 client.into_proxy(),
142 instance.to_owned(),
143 ),
144 )))
145 }
146}