realmbuilder_mock_helpers/
lib.rs1use anyhow::Error;
6use fidl::endpoints::{DiscoverableProtocolMarker, ProtocolMarker, Proxy};
7use fidl_fuchsia_device::{NameProviderMarker, NameProviderRequestStream};
8use fidl_fuchsia_stash::SecureStoreMarker;
9use fuchsia_async as fasync;
10use fuchsia_component::server::{ServiceFs, ServiceObj};
11use fuchsia_component_test::LocalComponentHandles;
12use futures::channel::mpsc;
13use futures::{SinkExt, StreamExt, TryStream, TryStreamExt};
14use log::info;
15use std::sync::Arc;
16use vfs::directory::entry_container::Directory;
17
18pub async fn process_request_stream<S, Event>(
23 mut stream: S::RequestStream,
24 mut sender: mpsc::Sender<Event>,
25) where
26 S: DiscoverableProtocolMarker,
27 Event: std::convert::From<<S::RequestStream as TryStream>::Ok>,
28 <S::RequestStream as TryStream>::Ok: std::fmt::Debug,
29{
30 while let Some(request) = stream.try_next().await.expect("serving request stream failed") {
31 info!("Received {} service request: {:?}", S::PROTOCOL_NAME, request);
32 sender.send(request.into()).await.expect("should send");
33 }
34}
35
36pub fn add_fidl_service_handler<S, Event: 'static>(
41 fs: &mut ServiceFs<ServiceObj<'_, ()>>,
42 sender: mpsc::Sender<Event>,
43) where
44 S: DiscoverableProtocolMarker,
45 Event: std::convert::From<S::RequestStream> + std::marker::Send,
46{
47 let _ = fs.dir("svc").add_fidl_service(move |req_stream: S::RequestStream| {
48 let mut s = sender.clone();
49 fasync::Task::local(async move {
50 info!("Received connection for {}", S::PROTOCOL_NAME);
51 s.send(req_stream.into()).await.expect("should send");
52 })
53 .detach()
54 });
55}
56
57pub async fn mock_component<S, Event: 'static>(
60 sender: mpsc::Sender<Event>,
61 handles: LocalComponentHandles,
62) -> Result<(), Error>
63where
64 S: DiscoverableProtocolMarker,
65 Event: std::convert::From<<<S as ProtocolMarker>::RequestStream as TryStream>::Ok>
66 + std::marker::Send,
67 <<S as ProtocolMarker>::RequestStream as TryStream>::Ok: std::fmt::Debug,
68{
69 let mut fs = ServiceFs::new();
70 let _ = fs.dir("svc").add_fidl_service(move |req_stream: S::RequestStream| {
71 let sender_clone = sender.clone();
72 info!("Received connection for {}", S::PROTOCOL_NAME);
73 fasync::Task::local(process_request_stream::<S, _>(req_stream, sender_clone)).detach();
74 });
75
76 let _ = fs.serve_connection(handles.outgoing_dir)?;
77 fs.collect::<()>().await;
78 Ok(())
79}
80
81pub async fn mock_dev(
83 handles: LocalComponentHandles,
84 dev_directory: Arc<dyn Directory>,
85) -> Result<(), Error> {
86 let mut fs = ServiceFs::new();
87 let _ = fs.add_remote(
88 "dev",
89 vfs::directory::serve_read_only(dev_directory, vfs::execution_scope::ExecutionScope::new()),
90 );
91 let _ = fs.serve_connection(handles.outgoing_dir)?;
92 fs.collect::<()>().await;
93 Ok(())
94}
95
96pub async fn mock_svc(
98 handles: LocalComponentHandles,
99 svc_directory: Arc<dyn Directory>,
100) -> Result<(), Error> {
101 let mut fs = ServiceFs::new();
102 let _ = fs.add_remote(
103 "svc",
104 vfs::directory::serve_read_only(svc_directory, vfs::execution_scope::ExecutionScope::new()),
105 );
106 let _ = fs.serve_connection(handles.outgoing_dir)?;
107 fs.collect::<()>().await;
108 Ok(())
109}
110
111pub async fn stateless_mock_responder<S, F>(
114 handles: LocalComponentHandles,
115 responder: F,
116) -> Result<(), anyhow::Error>
117where
118 S: DiscoverableProtocolMarker,
119 <<S as ProtocolMarker>::RequestStream as TryStream>::Ok: std::fmt::Debug,
120 F: Fn(<<S as ProtocolMarker>::RequestStream as TryStream>::Ok) -> Result<(), Error>
121 + Copy
122 + Send
123 + 'static,
124{
125 let mut fs = ServiceFs::new();
126 let _ = fs.dir("svc").add_fidl_service(
130 move |mut req_stream: <S as ProtocolMarker>::RequestStream| {
131 fasync::Task::local(async move {
132 let failure_msg = format!("serving {} request stream failed", S::DEBUG_NAME);
133 while let Some(req) = req_stream.try_next().await.expect(&failure_msg) {
134 let failed_to_respond = format!("failed to respond to req {:?}", req);
135 responder(req).expect(&failed_to_respond);
136 }
137 })
138 .detach()
139 },
140 );
141 let _ = fs.serve_connection(handles.outgoing_dir)?;
142 fs.collect::<()>().await;
143 Ok(())
144}
145
146pub fn provide_bt_gap_uses<Event>(
148 fs: &mut ServiceFs<ServiceObj<'_, ()>>,
149 sender: &mpsc::Sender<Event>,
150 handles: &LocalComponentHandles,
151) -> Result<(), Error>
152where
153 Event: From<SecureStoreMarker> + From<NameProviderRequestStream> + Send + 'static,
154{
155 let svc_dir = handles.clone_from_namespace("svc")?;
156 let sender_clone = Some(sender.clone());
157 let _ = fs.dir("svc").add_service_at(SecureStoreMarker::PROTOCOL_NAME, move |chan| {
158 let mut s = sender_clone.clone();
159 let svc_dir = Clone::clone(&svc_dir);
160 fasync::Task::local(async move {
161 info!(
162 "Proxying {} connection to real implementation",
163 SecureStoreMarker::PROTOCOL_NAME
164 );
165 fdio::service_connect_at(
166 svc_dir.as_channel().as_ref(),
167 SecureStoreMarker::PROTOCOL_NAME,
168 chan,
169 )
170 .expect("unable to forward secure store");
171 if let Some(mut sender) = s.take() {
174 sender.send(Event::from(SecureStoreMarker)).await.expect("should send");
175 }
176 })
177 .detach();
178 None
179 });
180 add_fidl_service_handler::<NameProviderMarker, _>(fs, sender.clone());
181 Ok(())
182}