fuchsia_driver_test/
lib.rs1use anyhow::{Context as _, Result};
6use cm_rust::push_box;
7use fuchsia_component_test::{Capability, ChildOptions, RealmBuilder, RealmInstance, Ref, Route};
8use {
9 fidl_fuchsia_component_test as ftest, fidl_fuchsia_driver_test as fdt, fidl_fuchsia_io as fio,
10};
11
12pub const COMPONENT_NAME: &str = "driver_test_realm";
13pub const DRIVER_TEST_REALM_URL: &str = "#meta/driver_test_realm.cm";
14
15#[async_trait::async_trait]
16pub trait DriverTestRealmBuilder {
17 async fn driver_test_realm_manifest_setup(&self, manifest_url: &str) -> Result<&Self>;
22 async fn driver_test_realm_setup(&self) -> Result<&Self>;
25
26 async fn driver_test_realm_add_dtr_exposes(
33 &self,
34 dtr_exposes: &Vec<ftest::Capability>,
35 ) -> Result<&Self>;
36
37 async fn driver_test_realm_add_dtr_offers(
44 &self,
45 dtr_offers: &Vec<ftest::Capability>,
46 from: Ref,
47 ) -> Result<&Self>;
48}
49
50#[async_trait::async_trait]
51impl DriverTestRealmBuilder for RealmBuilder {
52 async fn driver_test_realm_manifest_setup(&self, manifest_url: &str) -> Result<&Self> {
53 let driver_realm =
54 self.add_child(COMPONENT_NAME, manifest_url, ChildOptions::new().eager()).await?;
55
56 self.add_route(
60 Route::new()
61 .capability(Capability::protocol_by_name("fuchsia.logger.LogSink"))
62 .capability(Capability::protocol_by_name("fuchsia.inspect.InspectSink"))
63 .capability(Capability::protocol_by_name("fuchsia.diagnostics.ArchiveAccessor"))
64 .capability(Capability::protocol_by_name(
65 "fuchsia.component.resolution.Resolver-hermetic",
66 ))
67 .capability(Capability::protocol_by_name("fuchsia.pkg.PackageResolver-hermetic"))
68 .capability(Capability::dictionary("diagnostics"))
69 .from(Ref::parent())
70 .to(&driver_realm),
71 )
72 .await?;
73 self.add_route(
75 Route::new()
76 .capability(Capability::directory("dev-class").rights(fio::R_STAR_DIR))
77 .capability(Capability::directory("dev-topological").rights(fio::R_STAR_DIR))
78 .capability(Capability::protocol_by_name("fuchsia.system.state.Administrator"))
79 .capability(Capability::protocol_by_name("fuchsia.driver.development.Manager"))
80 .capability(Capability::protocol_by_name(
81 "fuchsia.driver.framework.CompositeNodeManager",
82 ))
83 .capability(Capability::protocol_by_name(
84 "fuchsia.driver.registrar.DriverRegistrar",
85 ))
86 .capability(Capability::protocol_by_name("fuchsia.driver.test.Realm"))
87 .from(&driver_realm)
88 .to(Ref::parent()),
89 )
90 .await?;
91 Ok(&self)
93 }
94
95 async fn driver_test_realm_setup(&self) -> Result<&Self> {
96 self.driver_test_realm_manifest_setup(DRIVER_TEST_REALM_URL).await
97 }
98
99 async fn driver_test_realm_add_dtr_exposes(
100 &self,
101 dtr_exposes: &Vec<ftest::Capability>,
102 ) -> Result<&Self> {
103 let mut decl = self.get_component_decl(COMPONENT_NAME).await?;
104 for expose in dtr_exposes {
105 let name = match expose {
106 fidl_fuchsia_component_test::Capability::Protocol(p) => p.name.as_ref(),
107 fidl_fuchsia_component_test::Capability::Directory(d) => d.name.as_ref(),
108 fidl_fuchsia_component_test::Capability::Storage(s) => s.name.as_ref(),
109 fidl_fuchsia_component_test::Capability::Service(s) => s.name.as_ref(),
110 fidl_fuchsia_component_test::Capability::EventStream(e) => e.name.as_ref(),
111 fidl_fuchsia_component_test::Capability::Config(c) => c.name.as_ref(),
112 fidl_fuchsia_component_test::Capability::Dictionary(d) => d.name.as_ref(),
113 _ => None,
114 };
115 let expose_parsed = name
116 .expect("No name found in capability.")
117 .parse::<cm_types::Name>()
118 .expect("Not a valid capability name");
119
120 push_box(
121 &mut decl.exposes,
122 cm_rust::ExposeDecl::Service(cm_rust::ExposeServiceDecl {
123 source: cm_rust::ExposeSource::Collection(
124 "realm_builder".parse::<cm_types::Name>().unwrap(),
125 ),
126 source_name: expose_parsed.clone(),
127 source_dictionary: Default::default(),
128 target_name: expose_parsed.clone(),
129 target: cm_rust::ExposeTarget::Parent,
130 availability: cm_rust::Availability::Required,
131 }),
132 );
133 }
134 self.replace_component_decl(COMPONENT_NAME, decl).await?;
135
136 for expose in dtr_exposes {
137 self.add_route(
139 Route::new()
140 .capability(expose.clone())
141 .from(Ref::child(COMPONENT_NAME))
142 .to(Ref::parent()),
143 )
144 .await?;
145 }
146
147 Ok(&self)
148 }
149
150 async fn driver_test_realm_add_dtr_offers(
151 &self,
152 dtr_offers: &Vec<ftest::Capability>,
153 from: Ref,
154 ) -> Result<&Self> {
155 let mut decl = self.get_component_decl(COMPONENT_NAME).await?;
156 for offer in dtr_offers {
157 let name = match offer {
158 fidl_fuchsia_component_test::Capability::Protocol(p) => p.name.as_ref(),
159 fidl_fuchsia_component_test::Capability::Directory(d) => d.name.as_ref(),
160 fidl_fuchsia_component_test::Capability::Storage(s) => s.name.as_ref(),
161 fidl_fuchsia_component_test::Capability::Service(s) => s.name.as_ref(),
162 fidl_fuchsia_component_test::Capability::EventStream(e) => e.name.as_ref(),
163 fidl_fuchsia_component_test::Capability::Config(c) => c.name.as_ref(),
164 fidl_fuchsia_component_test::Capability::Dictionary(d) => d.name.as_ref(),
165 _ => None,
166 };
167 let offer_parsed = name
168 .expect("No name found in capability.")
169 .parse::<cm_types::Name>()
170 .expect("Not a valid capability name");
171
172 push_box(
173 &mut decl.offers,
174 cm_rust::OfferDecl::Protocol(cm_rust::OfferProtocolDecl {
175 source: cm_rust::OfferSource::Parent,
176 source_name: offer_parsed.clone(),
177 source_dictionary: Default::default(),
178 target_name: offer_parsed.clone(),
179 target: cm_rust::OfferTarget::Collection(
180 "realm_builder".parse::<cm_types::Name>().unwrap(),
181 ),
182 dependency_type: cm_rust::DependencyType::Strong,
183 availability: cm_rust::Availability::Required,
184 }),
185 );
186 }
187 self.replace_component_decl(COMPONENT_NAME, decl).await?;
188
189 for offer in dtr_offers {
190 self.add_route(
192 Route::new()
193 .capability(offer.clone())
194 .from(from.clone())
195 .to(Ref::child(COMPONENT_NAME)),
196 )
197 .await?;
198 }
199
200 Ok(&self)
201 }
202}
203
204#[async_trait::async_trait]
205pub trait DriverTestRealmInstance {
206 async fn driver_test_realm_start(&self, args: fdt::RealmArgs) -> Result<()>;
208
209 fn driver_test_realm_connect_to_dev(&self) -> Result<fio::DirectoryProxy>;
211}
212
213#[async_trait::async_trait]
214impl DriverTestRealmInstance for RealmInstance {
215 async fn driver_test_realm_start(&self, args: fdt::RealmArgs) -> Result<()> {
216 let config: fdt::RealmProxy = self.root.connect_to_protocol_at_exposed_dir()?;
217 let () = config
218 .start(args)
219 .await
220 .context("DriverTestRealm Start failed")?
221 .map_err(zx_status::Status::from_raw)
222 .context("DriverTestRealm Start failed")?;
223 Ok(())
224 }
225
226 fn driver_test_realm_connect_to_dev(&self) -> Result<fio::DirectoryProxy> {
227 fuchsia_fs::directory::open_directory_async(
228 self.root.get_exposed_dir(),
229 "dev-topological",
230 fio::Flags::empty(),
231 )
232 .map_err(Into::into)
233 }
234}