bt_test_harness/
low_energy_peripheral.rs1use anyhow::{Context as _, Error};
6use fidl_fuchsia_bluetooth_le::{ConnectionProxy, PeripheralEvent, PeripheralProxy};
7use fidl_fuchsia_hardware_bluetooth::EmulatorProxy;
8use fuchsia_bluetooth::expectation::asynchronous::{
9 expectable, Expectable, ExpectableExt, ExpectableState,
10};
11use fuchsia_bluetooth::types::le::Peer;
12use futures::future::{self, BoxFuture};
13use futures::{FutureExt, TryFutureExt, TryStreamExt};
14use std::ops::{Deref, DerefMut};
15use std::sync::Arc;
16use test_harness::{SharedState, TestHarness, SHARED_STATE_TEST_COMPONENT_INDEX};
17
18use crate::core_realm::{CoreRealm, SHARED_STATE_INDEX};
19use crate::emulator::{watch_advertising_states, EmulatorState};
20use crate::host_watcher::ActivatedFakeHost;
21
22#[derive(Clone, Debug, Default)]
24pub struct PeripheralState {
25 emulator_state: EmulatorState,
26
27 pub connections: Vec<(Peer, ConnectionProxy)>,
29}
30
31impl PeripheralState {
32 pub fn reset(&mut self) {
34 self.emulator_state = EmulatorState::default();
35 self.connections.clear();
36 }
37}
38
39impl AsMut<EmulatorState> for PeripheralState {
40 fn as_mut(&mut self) -> &mut EmulatorState {
41 &mut self.emulator_state
42 }
43}
44
45impl AsRef<EmulatorState> for PeripheralState {
46 fn as_ref(&self) -> &EmulatorState {
47 &self.emulator_state
48 }
49}
50
51#[derive(Clone)]
52pub struct PeripheralHarness(Expectable<PeripheralState, Aux>);
53
54impl Deref for PeripheralHarness {
55 type Target = Expectable<PeripheralState, Aux>;
56
57 fn deref(&self) -> &Self::Target {
58 &self.0
59 }
60}
61
62impl DerefMut for PeripheralHarness {
63 fn deref_mut(&mut self) -> &mut Self::Target {
64 &mut self.0
65 }
66}
67
68pub struct Aux {
70 pub peripheral: PeripheralProxy,
71 emulator: EmulatorProxy,
72}
73
74impl AsRef<EmulatorProxy> for Aux {
75 fn as_ref(&self) -> &EmulatorProxy {
76 &self.emulator
77 }
78}
79
80impl TestHarness for PeripheralHarness {
81 type Env = (ActivatedFakeHost, Arc<CoreRealm>);
82 type Runner = BoxFuture<'static, Result<(), Error>>;
83
84 fn init(
85 shared_state: &Arc<SharedState>,
86 ) -> BoxFuture<'static, Result<(Self, Self::Env, Self::Runner), Error>> {
87 let shared_state = shared_state.clone();
88 async move {
89 let test_component: Arc<String> = shared_state
90 .get(SHARED_STATE_TEST_COMPONENT_INDEX)
91 .expect("SharedState must have TEST-COMPONENT")?;
92 let inserter = move || CoreRealm::create(test_component.to_string());
93 let realm = shared_state.get_or_insert_with(SHARED_STATE_INDEX, inserter).await?;
94 let host = ActivatedFakeHost::new(realm.clone()).await?;
95 let peripheral = realm
96 .instance()
97 .connect_to_protocol_at_exposed_dir()
98 .context("Failed to connect to BLE Peripheral service")?;
99 let harness = PeripheralHarness(expectable(
100 Default::default(),
101 Aux { peripheral, emulator: host.emulator().clone() },
102 ));
103
104 let watch_adv = watch_advertising_states(harness.deref().clone());
106 let watch_conn = watch_connections(harness.clone());
107 let run_peripheral =
108 future::try_join(watch_adv, watch_conn).map_ok(|((), ())| ()).boxed();
109
110 Ok((harness, (host, realm), run_peripheral))
111 }
112 .boxed()
113 }
114 fn terminate((emulator, realm): Self::Env) -> BoxFuture<'static, Result<(), Error>> {
115 async move {
117 let _realm = realm;
118 emulator.release().await
119 }
120 .boxed()
121 }
122}
123
124async fn watch_connections(harness: PeripheralHarness) -> Result<(), Error> {
125 let mut events = harness.aux().peripheral.take_event_stream();
126 while let Some(e) = events.try_next().await? {
127 match e {
128 PeripheralEvent::OnPeerConnected { peer, connection } => {
129 harness.write_state().connections.push((peer.try_into()?, connection.into_proxy()));
130 }
131 }
132 harness.notify_state_changed();
133 }
134 Ok(())
135}