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_route(
198 Route::new()
199 .capability(Capability::configuration("fuchsia.bluetooth.FastPairProvider"))
200 .capability(Capability::configuration("fuchsia.bluetooth.Rfcomm"))
201 .from(Ref::self_())
202 .to(&bt_init),
203 )
204 .await?;
205
206 let dtr_exposes = vec![Capability::service::<fhbt::ServiceMarker>().into()];
207 let _ = builder.driver_test_realm_add_dtr_exposes(&dtr_exposes).await?;
208
209 builder
210 .add_route(
211 Route::new()
212 .capability(Capability::service::<fhbt::ServiceMarker>())
213 .from(Ref::child(fuchsia_driver_test::COMPONENT_NAME))
214 .to(&bt_init),
215 )
216 .await?;
217
218 crate::host_realm::add_host_routes(&builder, &bt_init).await?;
219 let instance = builder.build().await?;
220
221 let args = fdt::RealmArgs {
223 root_driver: Some(EMULATOR_ROOT_DRIVER_URL.to_string()),
224 software_devices: Some(vec![fidl_fuchsia_driver_test::SoftwareDevice {
225 device_name: "bt-hci-emulator".to_string(),
226 device_id: bind_fuchsia_platform::BIND_PLATFORM_DEV_DID_BT_HCI_EMULATOR,
227 }]),
228 test_component: Some(resolved_test_component),
229 dtr_exposes: Some(dtr_exposes),
230 ..Default::default()
231 };
232 instance.driver_test_realm_start(args).await?;
233
234 Ok(Self { realm: instance })
235 }
236
237 pub fn instance(&self) -> &ScopedInstance {
238 &self.realm.root
239 }
240
241 pub fn dev(&self) -> Result<fio::DirectoryProxy, Error> {
242 self.realm.driver_test_realm_connect_to_dev()
243 }
244}