bt_test_harness/
core_realm.rs1use crate::emulator::EMULATOR_ROOT_DRIVER_URL;
6use anyhow::{Error, format_err};
7use fidl_fuchsia_bluetooth_bredr as fbredr;
8use fidl_fuchsia_bluetooth_gatt as fbgatt;
9use fidl_fuchsia_bluetooth_le as fble;
10use fidl_fuchsia_bluetooth_snoop::SnoopMarker;
11use fidl_fuchsia_bluetooth_sys as fbsys;
12use fidl_fuchsia_device::NameProviderMarker;
13use fidl_fuchsia_driver_test as fdt;
14use fidl_fuchsia_hardware_bluetooth as fhbt;
15use fidl_fuchsia_io as fio;
16use fidl_fuchsia_logger::LogSinkMarker;
17use fidl_fuchsia_stash::SecureStoreMarker;
18use fuchsia_component_test::{
19 Capability, ChildOptions, RealmBuilder, RealmInstance, Ref, Route, ScopedInstance,
20};
21use fuchsia_driver_test::{DriverTestRealmBuilder, DriverTestRealmInstance};
22use futures::FutureExt;
23use realmbuilder_mock_helpers::stateless_mock_responder;
24
25pub const SHARED_STATE_INDEX: &str = "BT-CORE-REALM";
26pub const DEFAULT_TEST_DEVICE_NAME: &str = "fuchsia-bt-integration-test";
27
28mod constants {
32 pub mod bt_init {
33 pub const URL: &str = "#meta/test-bt-init.cm";
34 pub const MONIKER: &str = "bt-init";
35 }
36 pub mod secure_stash {
37 pub const URL: &str = "#meta/test-stash-secure.cm";
38 pub const MONIKER: &str = "secure-stash";
39 }
40 pub mod mock_name_provider {
41 pub const MONIKER: &str = "mock-name-provider";
42 }
43 pub mod mock_snoop {
44 pub const MONIKER: &str = "mock-snoop";
45 }
46}
47
48pub struct CoreRealm {
55 realm: RealmInstance,
56}
57
58impl CoreRealm {
59 pub async fn create(test_component: String) -> Result<Self, Error> {
60 let resolved_test_component = {
63 let client = fuchsia_component::client::connect_to_protocol_at_path::<
64 fidl_fuchsia_component_resolution::ResolverMarker,
65 >("/svc/fuchsia.component.resolution.Resolver-hermetic")
66 .unwrap();
67 client
68 .resolve(test_component.as_str())
69 .await
70 .unwrap()
71 .expect("Failed to resolve test component")
72 };
73
74 let builder = RealmBuilder::new().await?;
75 let _ = builder.driver_test_realm_setup().await?;
76
77 let bt_init = builder
79 .add_child(
80 constants::bt_init::MONIKER,
81 constants::bt_init::URL,
82 ChildOptions::new().eager(),
83 )
84 .await?;
85 let secure_stash = builder
86 .add_child(
87 constants::secure_stash::MONIKER,
88 constants::secure_stash::URL,
89 ChildOptions::new(),
90 )
91 .await?;
92 let mock_name_provider = builder
93 .add_local_child(
94 constants::mock_name_provider::MONIKER,
95 |handles| {
96 stateless_mock_responder::<NameProviderMarker, _>(handles, |req| {
97 let responder = req
98 .into_get_device_name()
99 .ok_or_else(|| format_err!("got unexpected NameProviderRequest"))?;
100 Ok(responder.send(Ok(DEFAULT_TEST_DEVICE_NAME))?)
101 })
102 .boxed()
103 },
104 ChildOptions::new(),
105 )
106 .await?;
107 let mock_snoop = builder
108 .add_local_child(
109 constants::mock_snoop::MONIKER,
110 |handles| {
111 stateless_mock_responder::<SnoopMarker, _>(handles, |req| {
112 let _ = req
114 .into_start()
115 .ok_or_else(|| format_err!("got unexpected SnoopRequest"))?;
116 Ok(())
117 })
118 .boxed()
119 },
120 ChildOptions::new(),
121 )
122 .await?;
123
124 builder
126 .add_route(
127 Route::new()
128 .capability(Capability::protocol::<LogSinkMarker>())
129 .capability(Capability::dictionary("diagnostics"))
130 .from(Ref::parent())
131 .to(&bt_init)
132 .to(&secure_stash),
133 )
134 .await?;
135 builder
136 .add_route(
137 Route::new()
138 .capability(Capability::storage("tmp"))
139 .from(Ref::parent())
140 .to(&secure_stash),
141 )
142 .await?;
143 builder
144 .add_route(
145 Route::new()
146 .capability(Capability::protocol::<SecureStoreMarker>())
147 .from(&secure_stash)
148 .to(&bt_init),
149 )
150 .await?;
151 builder
152 .add_route(
153 Route::new()
154 .capability(Capability::protocol::<NameProviderMarker>())
155 .from(&mock_name_provider)
156 .to(&bt_init),
157 )
158 .await?;
159 builder
160 .add_route(
161 Route::new()
162 .capability(Capability::protocol::<SnoopMarker>())
163 .from(&mock_snoop)
164 .to(&bt_init),
165 )
166 .await?;
167 builder
168 .add_route(
169 Route::new()
170 .capability(Capability::protocol::<fbgatt::Server_Marker>())
171 .capability(Capability::protocol::<fble::CentralMarker>())
172 .capability(Capability::protocol::<fble::PeripheralMarker>())
173 .capability(Capability::protocol::<fbsys::AccessMarker>())
174 .capability(Capability::protocol::<fbsys::HostWatcherMarker>())
175 .capability(Capability::protocol::<fbredr::ProfileMarker>())
176 .capability(Capability::protocol::<fbsys::BootstrapMarker>())
177 .from(&bt_init)
178 .to(Ref::parent()),
179 )
180 .await?;
181
182 builder
185 .add_capability(cm_rust::CapabilityDecl::Config(cm_rust::ConfigurationDecl {
186 name: "fuchsia.bluetooth.FastPairProvider".parse()?,
187 value: cm_rust::ConfigValue::Single(cm_rust::ConfigSingleValue::Bool(false)),
188 }))
189 .await?;
190 builder
191 .add_capability(cm_rust::CapabilityDecl::Config(cm_rust::ConfigurationDecl {
192 name: "fuchsia.bluetooth.Rfcomm".parse()?,
193 value: cm_rust::ConfigValue::Single(cm_rust::ConfigSingleValue::Bool(true)),
194 }))
195 .await?;
196 builder
197 .add_capability(cm_rust::CapabilityDecl::Config(cm_rust::ConfigurationDecl {
198 name: "fuchsia.bluetooth.AutostartSnoop".parse()?,
199 value: cm_rust::ConfigValue::Single(cm_rust::ConfigSingleValue::Bool(true)),
200 }))
201 .await?;
202 builder
203 .add_capability(cm_rust::CapabilityDecl::Config(cm_rust::ConfigurationDecl {
204 name: "fuchsia.bluetooth.LePrivacy".parse()?,
205 value: cm_rust::ConfigValue::Single(cm_rust::ConfigSingleValue::Bool(true)),
206 }))
207 .await?;
208 builder
209 .add_capability(cm_rust::CapabilityDecl::Config(cm_rust::ConfigurationDecl {
210 name: "fuchsia.bluetooth.LeBackgroundScanning".parse()?,
211 value: cm_rust::ConfigValue::Single(cm_rust::ConfigSingleValue::Bool(false)),
212 }))
213 .await?;
214 builder
215 .add_capability(cm_rust::CapabilityDecl::Config(cm_rust::ConfigurationDecl {
216 name: "fuchsia.bluetooth.LeSecurityMode".parse()?,
217 value: cm_rust::ConfigValue::Single(cm_rust::ConfigSingleValue::String(
218 "Mode1".into(),
219 )),
220 }))
221 .await?;
222 builder
223 .add_capability(cm_rust::CapabilityDecl::Config(cm_rust::ConfigurationDecl {
224 name: "fuchsia.bluetooth.BredrConnectable".parse()?,
225 value: cm_rust::ConfigValue::Single(cm_rust::ConfigSingleValue::Bool(true)),
226 }))
227 .await?;
228 builder
229 .add_capability(cm_rust::CapabilityDecl::Config(cm_rust::ConfigurationDecl {
230 name: "fuchsia.bluetooth.BredrSecurityMode".parse()?,
231 value: cm_rust::ConfigValue::Single(cm_rust::ConfigSingleValue::String(
232 "Mode4".into(),
233 )),
234 }))
235 .await?;
236 builder
237 .add_route(
238 Route::new()
239 .capability(Capability::configuration("fuchsia.bluetooth.FastPairProvider"))
240 .capability(Capability::configuration("fuchsia.bluetooth.Rfcomm"))
241 .capability(Capability::configuration("fuchsia.bluetooth.AutostartSnoop"))
242 .capability(Capability::configuration("fuchsia.bluetooth.LePrivacy"))
243 .capability(Capability::configuration("fuchsia.bluetooth.LeBackgroundScanning"))
244 .capability(Capability::configuration("fuchsia.bluetooth.LeSecurityMode"))
245 .capability(Capability::configuration("fuchsia.bluetooth.BredrConnectable"))
246 .capability(Capability::configuration("fuchsia.bluetooth.BredrSecurityMode"))
247 .from(Ref::self_())
248 .to(&bt_init),
249 )
250 .await?;
251
252 let dtr_exposes = vec![Capability::service::<fhbt::ServiceMarker>().into()];
253 let _ = builder.driver_test_realm_add_dtr_exposes(&dtr_exposes).await?;
254
255 builder
256 .add_route(
257 Route::new()
258 .capability(Capability::service::<fhbt::ServiceMarker>())
259 .from(Ref::child(fuchsia_driver_test::COMPONENT_NAME))
260 .to(&bt_init),
261 )
262 .await?;
263
264 crate::host_realm::add_host_routes(&builder, &bt_init).await?;
265 let instance = builder.build().await?;
266
267 let args = fdt::RealmArgs {
269 root_driver: Some(EMULATOR_ROOT_DRIVER_URL.to_string()),
270 software_devices: Some(vec![fidl_fuchsia_driver_test::SoftwareDevice {
271 device_name: "bt-hci-emulator".to_string(),
272 device_id: bind_fuchsia_platform::BIND_PLATFORM_DEV_DID_BT_HCI_EMULATOR,
273 }]),
274 test_component: Some(resolved_test_component),
275 dtr_exposes: Some(dtr_exposes),
276 ..Default::default()
277 };
278 instance.driver_test_realm_start(args).await?;
279
280 Ok(Self { realm: instance })
281 }
282
283 pub fn instance(&self) -> &ScopedInstance {
284 &self.realm.root
285 }
286
287 pub fn dev(&self) -> Result<fio::DirectoryProxy, Error> {
288 self.realm.driver_test_realm_connect_to_dev()
289 }
290}