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