1use fidl::endpoints::ServerEnd;
6use {
7 fidl_fuchsia_component as fcomponent, fidl_fuchsia_component_decl as fdecl,
8 fidl_fuchsia_io as fio,
9};
10
11pub async fn create_child_component(
23 child_name: &str,
24 child_url: &str,
25 collection_name: &str,
26 create_child_args: fcomponent::CreateChildArgs,
27 realm: &fcomponent::RealmProxy,
28) -> Result<(), fcomponent::Error> {
29 let collection_ref = fdecl::CollectionRef { name: collection_name.to_string() };
30 let child_decl = fdecl::Child {
31 name: Some(child_name.to_string()),
32 url: Some(child_url.to_string()),
33 startup: Some(fdecl::StartupMode::Lazy),
34 environment: None,
35 ..Default::default()
36 };
37
38 realm
39 .create_child(&collection_ref, &child_decl, create_child_args)
40 .await
41 .map_err(|_| fcomponent::Error::Internal)?
42}
43
44pub async fn open_child_component_exposed_dir(
58 child_name: &str,
59 collection_name: &str,
60 realm: &fcomponent::RealmProxy,
61 exposed_dir: ServerEnd<fio::DirectoryMarker>,
62) -> Result<(), fcomponent::Error> {
63 let child_ref = fdecl::ChildRef {
64 name: child_name.to_string(),
65 collection: Some(collection_name.to_string()),
66 };
67
68 realm
69 .open_exposed_dir(&child_ref, exposed_dir)
70 .await
71 .map_err(|_| fcomponent::Error::Internal)?
72}
73
74pub async fn destroy_child_component(
85 child_name: &str,
86 collection_name: &str,
87 realm: &fcomponent::RealmProxy,
88) -> Result<(), fcomponent::Error> {
89 let child_ref = fdecl::ChildRef {
90 name: child_name.to_string(),
91 collection: Some(collection_name.to_string()),
92 };
93
94 realm.destroy_child(&child_ref).await.map_err(|_| fcomponent::Error::Internal)?
95}
96
97#[cfg(test)]
98mod tests {
99 use super::{
100 create_child_component, destroy_child_component, open_child_component_exposed_dir,
101 };
102 use fidl::endpoints::{create_endpoints, create_proxy};
103 use fidl_test_util::spawn_stream_handler;
104 use session_testing::spawn_directory_server;
105 use std::sync::LazyLock;
106 use test_util::Counter;
107 use {fidl_fuchsia_component as fcomponent, fidl_fuchsia_io as fio};
108
109 #[fuchsia::test]
111 async fn create_child_parameters() {
112 let child_name = "test_child";
113 let child_url = "test_url";
114 let child_collection = "test_collection";
115
116 let realm_proxy = spawn_stream_handler(move |realm_request| async move {
117 match realm_request {
118 fcomponent::RealmRequest::CreateChild { collection, decl, args: _, responder } => {
119 assert_eq!(decl.name.unwrap(), child_name);
120 assert_eq!(decl.url.unwrap(), child_url);
121 assert_eq!(&collection.name, child_collection);
122
123 let _ = responder.send(Ok(()));
124 }
125 _ => panic!("Realm handler received an unexpected request"),
126 }
127 });
128
129 assert!(
130 create_child_component(
131 child_name,
132 child_url,
133 child_collection,
134 Default::default(),
135 &realm_proxy
136 )
137 .await
138 .is_ok()
139 );
140 }
141
142 #[fuchsia::test]
145 async fn create_child_success() {
146 let realm_proxy = spawn_stream_handler(move |realm_request| async move {
147 match realm_request {
148 fcomponent::RealmRequest::CreateChild {
149 collection: _,
150 decl: _,
151 args: _,
152 responder,
153 } => {
154 let _ = responder.send(Ok(()));
155 }
156 _ => panic!("Realm handler received an unexpected request"),
157 }
158 });
159
160 assert!(create_child_component("", "", "", Default::default(), &realm_proxy).await.is_ok());
161 }
162
163 #[fuchsia::test]
166 async fn create_child_error() {
167 let realm_proxy = spawn_stream_handler(move |realm_request| async move {
168 match realm_request {
169 fcomponent::RealmRequest::CreateChild {
170 collection: _,
171 decl: _,
172 args: _,
173 responder,
174 } => {
175 let _ = responder.send(Err(fcomponent::Error::Internal));
176 }
177 _ => panic!("Realm handler received an unexpected request"),
178 }
179 });
180
181 assert!(
182 create_child_component("", "", "", Default::default(), &realm_proxy).await.is_err()
183 );
184 }
185
186 #[fuchsia::test]
188 async fn open_child_component_exposed_dir_parameters() {
189 let child_name = "test_child";
190 let child_collection = "test_collection";
191
192 let realm_proxy = spawn_stream_handler(move |realm_request| async move {
193 match realm_request {
194 fcomponent::RealmRequest::OpenExposedDir { child, exposed_dir: _, responder } => {
195 assert_eq!(child.name, child_name);
196 assert_eq!(child.collection, Some(child_collection.to_string()));
197
198 let _ = responder.send(Ok(()));
199 }
200 _ => panic!("Realm handler received an unexpected request"),
201 }
202 });
203
204 let (_exposed_dir, exposed_dir_server_end) = create_endpoints::<fio::DirectoryMarker>();
205 assert!(
206 open_child_component_exposed_dir(
207 child_name,
208 child_collection,
209 &realm_proxy,
210 exposed_dir_server_end
211 )
212 .await
213 .is_ok()
214 );
215 }
216
217 #[fuchsia::test]
220 async fn open_child_component_exposed_dir_success() {
221 let realm_proxy = spawn_stream_handler(move |realm_request| async move {
222 match realm_request {
223 fcomponent::RealmRequest::OpenExposedDir {
224 child: _,
225 exposed_dir: _,
226 responder,
227 } => {
228 let _ = responder.send(Ok(()));
229 }
230 _ => panic!("Realm handler received an unexpected request"),
231 }
232 });
233
234 let (_exposed_dir, exposed_dir_server_end) = create_endpoints::<fio::DirectoryMarker>();
235 assert!(
236 open_child_component_exposed_dir("", "", &realm_proxy, exposed_dir_server_end)
237 .await
238 .is_ok()
239 );
240 }
241
242 #[fuchsia::test]
244 async fn open_child_exposed_dir_success() {
245 static CALL_COUNT: LazyLock<Counter> = LazyLock::new(|| Counter::new(0));
247
248 let directory_request_handler = |directory_request| match directory_request {
249 fio::DirectoryRequest::Open { path: fake_capability_path, .. } => {
250 CALL_COUNT.inc();
251 assert_eq!(fake_capability_path, "fake_capability_path");
252 }
253 _ => panic!("Directory handler received an unexpected request"),
254 };
255
256 let realm_proxy = spawn_stream_handler(move |realm_request| async move {
257 match realm_request {
258 fcomponent::RealmRequest::OpenExposedDir { child: _, exposed_dir, responder } => {
259 CALL_COUNT.inc();
260 spawn_directory_server(exposed_dir, directory_request_handler);
261 let _ = responder.send(Ok(()));
262 }
263 _ => panic!("Realm handler received an unexpected request"),
264 }
265 });
266
267 let (exposed_dir, exposed_dir_server_end) = create_endpoints::<fio::DirectoryMarker>();
268 open_child_component_exposed_dir("", "", &realm_proxy, exposed_dir_server_end)
269 .await
270 .unwrap();
271
272 let (proxy, server_end) = create_proxy::<fio::DirectoryMarker>();
275
276 assert!(
279 fdio::service_connect_at(
280 &exposed_dir.into_channel(),
281 "fake_capability_path",
282 server_end.into_channel()
283 )
284 .is_ok()
285 );
286
287 assert!(proxy.rewind().await.is_err());
293
294 assert_eq!(CALL_COUNT.get(), 2);
296 }
297
298 #[fuchsia::test]
301 async fn open_child_component_exposed_dir_error() {
302 let realm_proxy = spawn_stream_handler(move |realm_request| async move {
303 match realm_request {
304 fcomponent::RealmRequest::OpenExposedDir {
305 child: _,
306 exposed_dir: _,
307 responder,
308 } => {
309 let _ = responder.send(Err(fcomponent::Error::Internal));
310 }
311 _ => panic!("Realm handler received an unexpected request"),
312 }
313 });
314
315 let (_exposed_dir, exposed_dir_server_end) = create_endpoints::<fio::DirectoryMarker>();
316 assert!(
317 open_child_component_exposed_dir("", "", &realm_proxy, exposed_dir_server_end)
318 .await
319 .is_err()
320 );
321 }
322
323 #[fuchsia::test]
325 async fn destroy_child_parameters() {
326 let child_name = "test_child";
327 let child_collection = "test_collection";
328
329 let realm_proxy = spawn_stream_handler(move |realm_request| async move {
330 match realm_request {
331 fcomponent::RealmRequest::DestroyChild { child, responder } => {
332 assert_eq!(child.name, child_name);
333 assert_eq!(child.collection, Some(child_collection.to_string()));
334
335 let _ = responder.send(Ok(()));
336 }
337 _ => panic!("Realm handler received an unexpected request"),
338 }
339 });
340
341 assert!(destroy_child_component(child_name, child_collection, &realm_proxy).await.is_ok());
342 }
343}