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