test_profile_server/
lib.rs1use fidl::endpoints::ServerEnd;
6use fidl_fuchsia_bluetooth as fidl_bt;
7use fidl_fuchsia_bluetooth_bredr as bredr;
8use fuchsia_bluetooth::types::{self as bt, PeerId};
9use futures::{Stream, StreamExt};
10use profile_client::ProfileClient;
11use std::pin::Pin;
12use std::task::{Context, Poll};
13
14pub struct TestProfileServerEndpoints {
15 pub proxy: bredr::ProfileProxy,
16 pub client: ProfileClient,
17 pub test_server: TestProfileServer,
18}
19
20#[derive(Debug)]
22pub enum ConnectChannel {
23 L2CapPsm(u16),
24 RfcommChannel(u8), }
26
27pub struct TestProfileServer {
33 profile_request_stream: bredr::ProfileRequestStream,
34 search_results_proxy: Option<bredr::SearchResultsProxy>,
35 connection_receiver_proxy: Option<bredr::ConnectionReceiverProxy>,
36 advertise_responder: Option<bredr::ProfileAdvertiseResponder>,
37}
38
39impl From<bredr::ProfileRequestStream> for TestProfileServer {
40 fn from(profile_request_stream: bredr::ProfileRequestStream) -> Self {
41 Self {
42 profile_request_stream,
43 search_results_proxy: None,
44 connection_receiver_proxy: None,
45 advertise_responder: None,
46 }
47 }
48}
49
50impl TestProfileServer {
51 pub fn new(
60 service_definition: Option<bredr::ServiceDefinition>,
61 service_class_profile_id: Option<bredr::ServiceClassProfileIdentifier>,
62 ) -> TestProfileServerEndpoints {
63 let (proxy, stream) = fidl::endpoints::create_proxy_and_stream::<bredr::ProfileMarker>();
64
65 let mut client = match service_definition {
66 None => ProfileClient::new(proxy.clone()),
67 Some(service_definition) => {
68 let channel_params = fidl_bt::ChannelParameters::default();
69 ProfileClient::advertise(proxy.clone(), vec![service_definition], channel_params)
70 .expect("Failed to advertise.")
71 }
72 };
73
74 if let Some(service_class_profile_id) = service_class_profile_id {
75 client.add_search(service_class_profile_id, None).expect("Failed to search for peers.");
76 }
77
78 let test_server = TestProfileServer::from(stream);
79
80 TestProfileServerEndpoints { proxy, client, test_server }
81 }
82
83 pub async fn expect_search(&mut self) {
84 let request = self.profile_request_stream.next().await;
85 match request {
86 Some(Ok(bredr::ProfileRequest::Search { payload, .. })) => {
87 self.search_results_proxy = Some(payload.results.unwrap().into_proxy());
88 }
89 _ => panic!(
90 "unexpected result on profile request stream while waiting for search: {request:?}"
91 ),
92 }
93 }
94
95 pub async fn expect_advertise(&mut self) {
96 let request = self.profile_request_stream.next().await;
97 match request {
98 Some(Ok(bredr::ProfileRequest::Advertise { payload, responder, .. })) => {
99 self.connection_receiver_proxy = Some(payload.receiver.unwrap().into_proxy());
100 if let Some(_old_responder) = self.advertise_responder.replace(responder) {
101 panic!("Got new advertise request before old request is complete.");
102 }
103 }
104 _ => panic!(
105 "unexpected result on profile request stream while waiting for advertisement: {request:?}"
106 ),
107 }
108 }
109
110 pub async fn expect_connect(
111 &mut self,
112 expected_channel: Option<ConnectChannel>,
113 ) -> bt::Channel {
114 let request = self.profile_request_stream.next().await;
115 match request {
116 Some(Ok(bredr::ProfileRequest::Connect { connection, responder, .. })) => {
117 match (expected_channel, connection) {
118 (None, _) => {}
119 (
120 Some(ConnectChannel::L2CapPsm(expected_psm)),
121 bredr::ConnectParameters::L2cap(bredr::L2capParameters {
122 psm: psm_option,
123 ..
124 }),
125 ) => assert_eq!(Some(expected_psm), psm_option),
126 (
127 Some(ConnectChannel::RfcommChannel(expected_channel)),
128 bredr::ConnectParameters::Rfcomm(bredr::RfcommParameters {
129 channel: channel_option,
130 ..
131 }),
132 ) => assert_eq!(Some(expected_channel), channel_option),
133 (expected_channel, connection) => {
134 panic!("On connect, expected {expected_channel:?}, got {connection:?}")
135 }
136 }
137
138 let (near_bt_channel, far_bt_channel) = bt::Channel::create_socket_pair();
139 let far_bredr_channel: bredr::Channel =
140 far_bt_channel.try_into().expect("BT Channel into FIDL BREDR Channel");
141 responder.send(Ok(far_bredr_channel)).expect("Send channel");
142 near_bt_channel
143 }
144 _ => panic!(
145 "Unexpected result on profile request stream expecting connection: {request:?}",
146 ),
147 }
148 }
149
150 pub async fn expect_sco_connect(
151 &mut self,
152 expected_initiator: bool,
153 ) -> ServerEnd<bredr::ScoConnectionMarker> {
154 let request = self.profile_request_stream.next().await;
155 let connection = match request {
156 Some(Ok(bredr::ProfileRequest::ConnectSco {
157 payload: bredr::ProfileConnectScoRequest { initiator, connection, .. },
158 ..
159 })) if initiator == Some(expected_initiator) => connection,
160 Some(Ok(bredr::ProfileRequest::ConnectSco {
161 payload: bredr::ProfileConnectScoRequest { initiator, .. },
162 ..
163 })) => {
164 panic!(
165 "Got SCO connection request expected initatior: {expected_initiator:}, actual initiator: {initiator:?}"
166 );
167 }
168 _ => panic!(
169 "Unexpected result on profile request stream expecting SCO connection: {request:?}",
170 ),
171 };
172
173 connection.expect("Got no connection when expecting SCO connection.")
174 }
175
176 pub fn send_service_found(
177 &mut self,
178 peer_id: PeerId,
179 protocol_list: Option<Vec<bredr::ProtocolDescriptor>>,
180 attributes: Vec<bredr::Attribute>,
181 ) -> fidl::client::QueryResponseFut<()> {
182 let search_results_proxy = self.search_results_proxy.as_ref().expect("Search result proxy");
183 search_results_proxy.service_found(&peer_id.into(), protocol_list.as_deref(), &attributes)
184 }
185
186 pub fn send_connected(
187 &mut self,
188 peer_id: PeerId,
189 protocol_list: Vec<bredr::ProtocolDescriptor>,
190 ) -> bt::Channel {
191 let (near_bt_channel, far_bt_channel) = bt::Channel::create_socket_pair();
192 let far_bredr_channel: bredr::Channel =
193 far_bt_channel.try_into().expect("BT Channel into FIDL BREDR Channel");
194
195 let connection_receiver_proxy =
196 self.connection_receiver_proxy.as_ref().expect("Connection receiver proxy");
197 connection_receiver_proxy
198 .connected(&peer_id.into(), far_bredr_channel, &protocol_list)
199 .expect("Connected");
200
201 near_bt_channel
202 }
203}
204
205impl Stream for TestProfileServer {
207 type Item = Result<bredr::ProfileRequest, fidl::Error>;
208
209 fn poll_next(mut self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll<Option<Self::Item>> {
210 let pinned_stream = Pin::new(&mut self.profile_request_stream);
211 pinned_stream.poll_next(context)
212 }
213}
214
215impl Drop for TestProfileServer {
216 fn drop(&mut self) {
217 if let Some(responder) = self.advertise_responder.take() {
219 responder
220 .send(Ok(&bredr::ProfileAdvertiseResponse::default()))
221 .expect("Drop responder");
222 }
223 }
224}