bt_test_harness/
core_realm.rs1use crate::emulator::EMULATOR_ROOT_DRIVER_URL;
6use anyhow::{format_err, Error};
7use fidl_fuchsia_bluetooth_snoop::SnoopMarker;
8use fidl_fuchsia_device::NameProviderMarker;
9use fidl_fuchsia_logger::LogSinkMarker;
10use fidl_fuchsia_stash::SecureStoreMarker;
11use fuchsia_component_test::{
12 Capability, ChildOptions, RealmBuilder, RealmInstance, Ref, Route, ScopedInstance,
13};
14use fuchsia_driver_test::{DriverTestRealmBuilder, DriverTestRealmInstance};
15use futures::FutureExt;
16use realmbuilder_mock_helpers::stateless_mock_responder;
17use {
18 fidl_fuchsia_bluetooth_bredr as fbredr, fidl_fuchsia_bluetooth_gatt as fbgatt,
19 fidl_fuchsia_bluetooth_le as fble, fidl_fuchsia_bluetooth_sys as fbsys,
20 fidl_fuchsia_driver_test as fdt, fidl_fuchsia_io as fio,
21};
22
23pub const SHARED_STATE_INDEX: &str = "BT-CORE-REALM";
24pub const DEFAULT_TEST_DEVICE_NAME: &str = "fuchsia-bt-integration-test";
25
26mod constants {
30 pub mod bt_init {
31 pub const URL: &str = "#meta/test-bt-init.cm";
32 pub const MONIKER: &str = "bt-init";
33 }
34 pub mod secure_stash {
35 pub const URL: &str = "#meta/test-stash-secure.cm";
36 pub const MONIKER: &str = "secure-stash";
37 }
38 pub mod mock_name_provider {
39 pub const MONIKER: &str = "mock-name-provider";
40 }
41 pub mod mock_snoop {
42 pub const MONIKER: &str = "mock-snoop";
43 }
44}
45
46pub struct CoreRealm {
53 realm: RealmInstance,
54}
55
56impl CoreRealm {
57 pub async fn create(test_component: String) -> Result<Self, Error> {
58 let resolved_test_component = {
61 let client = fuchsia_component::client::connect_to_protocol_at_path::<
62 fidl_fuchsia_component_resolution::ResolverMarker,
63 >("/svc/fuchsia.component.resolution.Resolver-hermetic")
64 .unwrap();
65 client
66 .resolve(test_component.as_str())
67 .await
68 .unwrap()
69 .expect("Failed to resolve test component")
70 };
71
72 let builder = RealmBuilder::new().await?;
73 let _ = builder.driver_test_realm_setup().await?;
74
75 let bt_init = builder
77 .add_child(
78 constants::bt_init::MONIKER,
79 constants::bt_init::URL,
80 ChildOptions::new().eager(),
81 )
82 .await?;
83 let secure_stash = builder
84 .add_child(
85 constants::secure_stash::MONIKER,
86 constants::secure_stash::URL,
87 ChildOptions::new(),
88 )
89 .await?;
90 let mock_name_provider = builder
91 .add_local_child(
92 constants::mock_name_provider::MONIKER,
93 |handles| {
94 stateless_mock_responder::<NameProviderMarker, _>(handles, |req| {
95 let responder = req
96 .into_get_device_name()
97 .ok_or(format_err!("got unexpected NameProviderRequest"))?;
98 Ok(responder.send(Ok(DEFAULT_TEST_DEVICE_NAME))?)
99 })
100 .boxed()
101 },
102 ChildOptions::new(),
103 )
104 .await?;
105 let mock_snoop = builder
106 .add_local_child(
107 constants::mock_snoop::MONIKER,
108 |handles| {
109 stateless_mock_responder::<SnoopMarker, _>(handles, |req| {
110 let _ =
112 req.into_start().ok_or(format_err!("got unexpected SnoopRequest"))?;
113 Ok(())
114 })
115 .boxed()
116 },
117 ChildOptions::new(),
118 )
119 .await?;
120
121 builder
123 .add_route(
124 Route::new()
125 .capability(Capability::protocol::<LogSinkMarker>())
126 .capability(Capability::dictionary("diagnostics"))
127 .from(Ref::parent())
128 .to(&bt_init)
129 .to(&secure_stash),
130 )
131 .await?;
132 builder
133 .add_route(
134 Route::new()
135 .capability(Capability::storage("tmp"))
136 .from(Ref::parent())
137 .to(&secure_stash),
138 )
139 .await?;
140 builder
141 .add_route(
142 Route::new()
143 .capability(Capability::protocol::<SecureStoreMarker>())
144 .from(&secure_stash)
145 .to(&bt_init),
146 )
147 .await?;
148 builder
149 .add_route(
150 Route::new()
151 .capability(Capability::protocol::<NameProviderMarker>())
152 .from(&mock_name_provider)
153 .to(&bt_init),
154 )
155 .await?;
156 builder
157 .add_route(
158 Route::new()
159 .capability(Capability::protocol::<SnoopMarker>())
160 .from(&mock_snoop)
161 .to(&bt_init),
162 )
163 .await?;
164 builder
165 .add_route(
166 Route::new()
167 .capability(Capability::protocol::<fbgatt::Server_Marker>())
168 .capability(Capability::protocol::<fble::CentralMarker>())
169 .capability(Capability::protocol::<fble::PeripheralMarker>())
170 .capability(Capability::protocol::<fbsys::AccessMarker>())
171 .capability(Capability::protocol::<fbsys::HostWatcherMarker>())
172 .capability(Capability::protocol::<fbredr::ProfileMarker>())
173 .capability(Capability::protocol::<fbsys::BootstrapMarker>())
174 .from(&bt_init)
175 .to(Ref::parent()),
176 )
177 .await?;
178
179 builder
181 .add_capability(cm_rust::CapabilityDecl::Config(cm_rust::ConfigurationDecl {
182 name: "fuchsia.bluetooth.LegacyPairing".parse()?,
183 value: cm_rust::ConfigValue::Single(cm_rust::ConfigSingleValue::Bool(false)),
184 }))
185 .await?;
186
187 builder
188 .add_route(
189 Route::new()
190 .capability(Capability::configuration("fuchsia.bluetooth.LegacyPairing"))
191 .from(Ref::self_())
192 .to(&bt_init),
193 )
194 .await?;
195
196 builder
198 .add_route(
199 Route::new()
200 .capability(
201 Capability::directory("dev-class").subdir("bt-hci").as_("dev-bt-hci"),
202 )
203 .from(Ref::child(fuchsia_driver_test::COMPONENT_NAME))
204 .to(&bt_init),
205 )
206 .await?;
207
208 let instance = builder.build().await?;
209
210 let args = fdt::RealmArgs {
212 root_driver: Some(EMULATOR_ROOT_DRIVER_URL.to_string()),
213 software_devices: Some(vec![fidl_fuchsia_driver_test::SoftwareDevice {
214 device_name: "bt-hci-emulator".to_string(),
215 device_id: bind_fuchsia_platform::BIND_PLATFORM_DEV_DID_BT_HCI_EMULATOR,
216 }]),
217 test_component: Some(resolved_test_component),
218 ..Default::default()
219 };
220 instance.driver_test_realm_start(args).await?;
221
222 Ok(Self { realm: instance })
223 }
224
225 pub fn instance(&self) -> &ScopedInstance {
226 &self.realm.root
227 }
228
229 pub fn dev(&self) -> Result<fio::DirectoryProxy, Error> {
230 self.realm.driver_test_realm_connect_to_dev()
231 }
232}