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 lazy_static::lazy_static;
105 use session_testing::spawn_directory_server;
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!(create_child_component(
130 child_name,
131 child_url,
132 child_collection,
133 Default::default(),
134 &realm_proxy
135 )
136 .await
137 .is_ok());
138 }
139
140 #[fuchsia::test]
143 async fn create_child_success() {
144 let realm_proxy = spawn_stream_handler(move |realm_request| async move {
145 match realm_request {
146 fcomponent::RealmRequest::CreateChild {
147 collection: _,
148 decl: _,
149 args: _,
150 responder,
151 } => {
152 let _ = responder.send(Ok(()));
153 }
154 _ => panic!("Realm handler received an unexpected request"),
155 }
156 });
157
158 assert!(create_child_component("", "", "", Default::default(), &realm_proxy).await.is_ok());
159 }
160
161 #[fuchsia::test]
164 async fn create_child_error() {
165 let realm_proxy = spawn_stream_handler(move |realm_request| async move {
166 match realm_request {
167 fcomponent::RealmRequest::CreateChild {
168 collection: _,
169 decl: _,
170 args: _,
171 responder,
172 } => {
173 let _ = responder.send(Err(fcomponent::Error::Internal));
174 }
175 _ => panic!("Realm handler received an unexpected request"),
176 }
177 });
178
179 assert!(create_child_component("", "", "", Default::default(), &realm_proxy)
180 .await
181 .is_err());
182 }
183
184 #[fuchsia::test]
186 async fn open_child_component_exposed_dir_parameters() {
187 let child_name = "test_child";
188 let child_collection = "test_collection";
189
190 let realm_proxy = spawn_stream_handler(move |realm_request| async move {
191 match realm_request {
192 fcomponent::RealmRequest::OpenExposedDir { child, exposed_dir: _, responder } => {
193 assert_eq!(child.name, child_name);
194 assert_eq!(child.collection, Some(child_collection.to_string()));
195
196 let _ = responder.send(Ok(()));
197 }
198 _ => panic!("Realm handler received an unexpected request"),
199 }
200 });
201
202 let (_exposed_dir, exposed_dir_server_end) = create_endpoints::<fio::DirectoryMarker>();
203 assert!(open_child_component_exposed_dir(
204 child_name,
205 child_collection,
206 &realm_proxy,
207 exposed_dir_server_end
208 )
209 .await
210 .is_ok());
211 }
212
213 #[fuchsia::test]
216 async fn open_child_component_exposed_dir_success() {
217 let realm_proxy = spawn_stream_handler(move |realm_request| async move {
218 match realm_request {
219 fcomponent::RealmRequest::OpenExposedDir {
220 child: _,
221 exposed_dir: _,
222 responder,
223 } => {
224 let _ = responder.send(Ok(()));
225 }
226 _ => panic!("Realm handler received an unexpected request"),
227 }
228 });
229
230 let (_exposed_dir, exposed_dir_server_end) = create_endpoints::<fio::DirectoryMarker>();
231 assert!(open_child_component_exposed_dir("", "", &realm_proxy, exposed_dir_server_end)
232 .await
233 .is_ok());
234 }
235
236 #[fuchsia::test]
238 async fn open_child_exposed_dir_success() {
239 lazy_static! {
241 static ref CALL_COUNT: Counter = Counter::new(0);
242 }
243
244 let directory_request_handler = |directory_request| match directory_request {
245 fio::DirectoryRequest::Open { path: fake_capability_path, .. } => {
246 CALL_COUNT.inc();
247 assert_eq!(fake_capability_path, "fake_capability_path");
248 }
249 _ => panic!("Directory handler received an unexpected request"),
250 };
251
252 let realm_proxy = spawn_stream_handler(move |realm_request| async move {
253 match realm_request {
254 fcomponent::RealmRequest::OpenExposedDir { child: _, exposed_dir, responder } => {
255 CALL_COUNT.inc();
256 spawn_directory_server(exposed_dir, directory_request_handler);
257 let _ = responder.send(Ok(()));
258 }
259 _ => panic!("Realm handler received an unexpected request"),
260 }
261 });
262
263 let (exposed_dir, exposed_dir_server_end) = create_endpoints::<fio::DirectoryMarker>();
264 open_child_component_exposed_dir("", "", &realm_proxy, exposed_dir_server_end)
265 .await
266 .unwrap();
267
268 let (proxy, server_end) = create_proxy::<fio::DirectoryMarker>();
271
272 assert!(fdio::service_connect_at(
275 &exposed_dir.into_channel(),
276 "fake_capability_path",
277 server_end.into_channel()
278 )
279 .is_ok());
280
281 assert!(proxy.rewind().await.is_err());
287
288 assert_eq!(CALL_COUNT.get(), 2);
290 }
291
292 #[fuchsia::test]
295 async fn open_child_component_exposed_dir_error() {
296 let realm_proxy = spawn_stream_handler(move |realm_request| async move {
297 match realm_request {
298 fcomponent::RealmRequest::OpenExposedDir {
299 child: _,
300 exposed_dir: _,
301 responder,
302 } => {
303 let _ = responder.send(Err(fcomponent::Error::Internal));
304 }
305 _ => panic!("Realm handler received an unexpected request"),
306 }
307 });
308
309 let (_exposed_dir, exposed_dir_server_end) = create_endpoints::<fio::DirectoryMarker>();
310 assert!(open_child_component_exposed_dir("", "", &realm_proxy, exposed_dir_server_end)
311 .await
312 .is_err());
313 }
314
315 #[fuchsia::test]
317 async fn destroy_child_parameters() {
318 let child_name = "test_child";
319 let child_collection = "test_collection";
320
321 let realm_proxy = spawn_stream_handler(move |realm_request| async move {
322 match realm_request {
323 fcomponent::RealmRequest::DestroyChild { child, responder } => {
324 assert_eq!(child.name, child_name);
325 assert_eq!(child.collection, Some(child_collection.to_string()));
326
327 let _ = responder.send(Ok(()));
328 }
329 _ => panic!("Realm handler received an unexpected request"),
330 }
331 });
332
333 assert!(destroy_child_component(child_name, child_collection, &realm_proxy).await.is_ok());
334 }
335}