realmbuilder_mock_helpers/
lib.rsuse anyhow::Error;
use fidl::endpoints::{DiscoverableProtocolMarker, ProtocolMarker, Proxy};
use fidl_fuchsia_device::{NameProviderMarker, NameProviderRequestStream};
use fidl_fuchsia_stash::SecureStoreMarker;
use fuchsia_async as fasync;
use fuchsia_component::server::{ServiceFs, ServiceObj};
use fuchsia_component_test::LocalComponentHandles;
use futures::channel::mpsc;
use futures::{SinkExt, StreamExt, TryStream, TryStreamExt};
use std::sync::Arc;
use tracing::info;
use vfs::directory::entry_container::Directory;
use vfs::directory::spawn_directory;
pub async fn process_request_stream<S, Event>(
mut stream: S::RequestStream,
mut sender: mpsc::Sender<Event>,
) where
S: DiscoverableProtocolMarker,
Event: std::convert::From<<S::RequestStream as TryStream>::Ok>,
<S::RequestStream as TryStream>::Ok: std::fmt::Debug,
{
while let Some(request) = stream.try_next().await.expect("serving request stream failed") {
info!("Received {} service request: {:?}", S::PROTOCOL_NAME, request);
sender.send(request.into()).await.expect("should send");
}
}
pub fn add_fidl_service_handler<S, Event: 'static>(
fs: &mut ServiceFs<ServiceObj<'_, ()>>,
sender: mpsc::Sender<Event>,
) where
S: DiscoverableProtocolMarker,
Event: std::convert::From<S::RequestStream> + std::marker::Send,
{
let _ = fs.dir("svc").add_fidl_service(move |req_stream: S::RequestStream| {
let mut s = sender.clone();
fasync::Task::local(async move {
info!("Received connection for {}", S::PROTOCOL_NAME);
s.send(req_stream.into()).await.expect("should send");
})
.detach()
});
}
pub async fn mock_component<S, Event: 'static>(
sender: mpsc::Sender<Event>,
handles: LocalComponentHandles,
) -> Result<(), Error>
where
S: DiscoverableProtocolMarker,
Event: std::convert::From<<<S as ProtocolMarker>::RequestStream as TryStream>::Ok>
+ std::marker::Send,
<<S as ProtocolMarker>::RequestStream as TryStream>::Ok: std::fmt::Debug,
{
let mut fs = ServiceFs::new();
let _ = fs.dir("svc").add_fidl_service(move |req_stream: S::RequestStream| {
let sender_clone = sender.clone();
info!("Received connection for {}", S::PROTOCOL_NAME);
fasync::Task::local(process_request_stream::<S, _>(req_stream, sender_clone)).detach();
});
let _ = fs.serve_connection(handles.outgoing_dir)?;
fs.collect::<()>().await;
Ok(())
}
pub async fn mock_dev(
handles: LocalComponentHandles,
dev_directory: Arc<dyn Directory>,
) -> Result<(), Error> {
let mut fs = ServiceFs::new();
let _ = fs.add_remote("dev", spawn_directory(dev_directory));
let _ = fs.serve_connection(handles.outgoing_dir)?;
fs.collect::<()>().await;
Ok(())
}
pub async fn stateless_mock_responder<S, F>(
handles: LocalComponentHandles,
responder: F,
) -> Result<(), anyhow::Error>
where
S: DiscoverableProtocolMarker,
<<S as ProtocolMarker>::RequestStream as TryStream>::Ok: std::fmt::Debug,
F: Fn(<<S as ProtocolMarker>::RequestStream as TryStream>::Ok) -> Result<(), Error>
+ Copy
+ Send
+ 'static,
{
let mut fs = ServiceFs::new();
let _ = fs.dir("svc").add_fidl_service(
move |mut req_stream: <S as ProtocolMarker>::RequestStream| {
fasync::Task::local(async move {
let failure_msg = format!("serving {} request stream failed", S::DEBUG_NAME);
while let Some(req) = req_stream.try_next().await.expect(&failure_msg) {
let failed_to_respond = format!("failed to respond to req {:?}", req);
responder(req).expect(&failed_to_respond);
}
})
.detach()
},
);
let _ = fs.serve_connection(handles.outgoing_dir)?;
fs.collect::<()>().await;
Ok(())
}
pub fn provide_bt_gap_uses<Event>(
fs: &mut ServiceFs<ServiceObj<'_, ()>>,
sender: &mpsc::Sender<Event>,
handles: &LocalComponentHandles,
) -> Result<(), Error>
where
Event: From<SecureStoreMarker> + From<NameProviderRequestStream> + Send + 'static,
{
let svc_dir = handles.clone_from_namespace("svc")?;
let sender_clone = Some(sender.clone());
let _ = fs.dir("svc").add_service_at(SecureStoreMarker::PROTOCOL_NAME, move |chan| {
let mut s = sender_clone.clone();
let svc_dir = Clone::clone(&svc_dir);
fasync::Task::local(async move {
info!(
"Proxying {} connection to real implementation",
SecureStoreMarker::PROTOCOL_NAME
);
fdio::service_connect_at(
svc_dir.as_channel().as_ref(),
SecureStoreMarker::PROTOCOL_NAME,
chan,
)
.expect("unable to forward secure store");
if let Some(mut sender) = s.take() {
sender.send(Event::from(SecureStoreMarker)).await.expect("should send");
}
})
.detach();
None
});
add_fidl_service_handler::<NameProviderMarker, _>(fs, sender.clone());
Ok(())
}