1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
// Copyright 2023 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::{bail, Result};
use fidl::endpoints::{
create_endpoints, ClientEnd, DiscoverableProtocolMarker, ServerEnd, ServiceMarker, ServiceProxy,
};
use fidl_fuchsia_io as fio;
use fidl_fuchsia_testing_harness::{RealmProxy_Marker, RealmProxy_Proxy};
use fuchsia_component::client::connect_to_protocol;
pub mod error;
pub use error::Error;
// RealmProxyClient is a client for fuchsia.testing.harness.RealmProxy.
//
// The calling component must have a handle to the RealmProxy protocol in
// order to use this struct. Once the caller has connected to the RealmProxy
// service, they can access the other services in the proxied test realm by
// calling [connect_to_protocol].
//
// # Example Usage
//
// ```
// let realm_proxy = RealmProxyClient::connect()?;
// let echo = realm_proxy.connect_to_protocol::<EchoMarker>().await?;
// ```
pub struct RealmProxyClient {
inner: RealmProxy_Proxy,
}
impl From<RealmProxy_Proxy> for RealmProxyClient {
fn from(value: RealmProxy_Proxy) -> Self {
Self { inner: value }
}
}
impl From<ClientEnd<RealmProxy_Marker>> for RealmProxyClient {
fn from(value: ClientEnd<RealmProxy_Marker>) -> Self {
let inner = value.into_proxy().expect("ClientEnd::into_proxy");
Self { inner }
}
}
impl RealmProxyClient {
// Connects to the RealmProxy service.
pub fn connect() -> Result<Self, anyhow::Error> {
let inner = connect_to_protocol::<RealmProxy_Marker>()?;
Ok(Self { inner })
}
// Connects to the protocol marked by [T] via the proxy.
//
// Returns an error if the connection fails.
pub async fn connect_to_protocol<T: DiscoverableProtocolMarker>(
&self,
) -> Result<T::Proxy, anyhow::Error> {
self.connect_to_named_protocol::<T>(T::PROTOCOL_NAME).await
}
// Connects the `sever_end` to the protocol marked by [T] via the proxy.
//
// Returns an error if the connection fails.
pub async fn connect_server_end_to_protocol<T: DiscoverableProtocolMarker>(
&self,
server_end: ServerEnd<T>,
) -> Result<(), anyhow::Error> {
self.connect_server_end_to_named_protocol::<T>(T::PROTOCOL_NAME, server_end).await
}
// Connects to the protocol with the given name, via the proxy.
//
// Returns an error if the connection fails.
pub async fn connect_to_named_protocol<T: DiscoverableProtocolMarker>(
&self,
protocol_name: &str,
) -> Result<T::Proxy, anyhow::Error> {
let (client, server) = create_endpoints::<T>();
self.connect_server_end_to_named_protocol(protocol_name, server).await?;
Ok(client.into_proxy()?)
}
// Connects the `server_end` to the protocol with the given name, via the proxy.
//
// Returns an error if the connection fails.
pub async fn connect_server_end_to_named_protocol<T: DiscoverableProtocolMarker>(
&self,
protocol_name: &str,
server_end: ServerEnd<T>,
) -> Result<(), anyhow::Error> {
let res =
self.inner.connect_to_named_protocol(protocol_name, server_end.into_channel()).await?;
if let Some(op_err) = res.err() {
bail!("{:?}", op_err);
}
Ok(())
}
// Opens the given service capability, via the proxy.
//
// See https://fuchsia.dev/fuchsia-src/concepts/components/v2/capabilities/service
// for more information about service capabilities.
//
// Returns an error if the connection fails.
pub async fn open_service<T: ServiceMarker>(
&self,
) -> Result<fio::DirectoryProxy, anyhow::Error> {
let (client, server) = create_endpoints::<fio::DirectoryMarker>();
let res = self.inner.open_service(T::SERVICE_NAME, server.into_channel()).await?;
if let Some(op_err) = res.err() {
bail!("{:?}", op_err);
}
Ok(client.into_proxy()?)
}
// Connects to the given service instance, via the proxy.
//
// See https://fuchsia.dev/fuchsia-src/concepts/components/v2/capabilities/service
// for more information about service capabilities.
//
// Returns an error if the connection fails.
pub async fn connect_to_service_instance<T: ServiceMarker>(
&self,
instance: &str,
) -> Result<T::Proxy, anyhow::Error> {
let (client, server) = create_endpoints::<fio::DirectoryMarker>();
let res = self
.inner
.connect_to_service_instance(T::SERVICE_NAME, instance, server.into_channel())
.await?;
if let Some(op_err) = res.err() {
bail!("{:?}", op_err);
}
Ok(T::Proxy::from_member_opener(Box::new(
fuchsia_component::client::ServiceInstanceDirectory(client.into_proxy()?),
)))
}
}