test_profile_server/
lib.rs1use fuchsia_bluetooth::types::{self as bt, PeerId};
6use futures::{Stream, StreamExt};
7use profile_client::ProfileClient;
8use std::pin::Pin;
9use std::task::{Context, Poll};
10use {fidl_fuchsia_bluetooth as fidl_bt, fidl_fuchsia_bluetooth_bredr as bredr};
11
12pub struct TestProfileServerEndpoints {
13 pub proxy: bredr::ProfileProxy,
14 pub client: ProfileClient,
15 pub test_server: TestProfileServer,
16}
17
18#[derive(Debug)]
20pub enum ConnectChannel {
21 L2CapPsm(u16),
22 RfcommChannel(u8), }
24
25pub struct TestProfileServer {
31 profile_request_stream: bredr::ProfileRequestStream,
32 search_results_proxy: Option<bredr::SearchResultsProxy>,
33 connection_receiver_proxy: Option<bredr::ConnectionReceiverProxy>,
34 advertise_responder: Option<bredr::ProfileAdvertiseResponder>,
35}
36
37impl From<bredr::ProfileRequestStream> for TestProfileServer {
38 fn from(profile_request_stream: bredr::ProfileRequestStream) -> Self {
39 Self {
40 profile_request_stream,
41 search_results_proxy: None,
42 connection_receiver_proxy: None,
43 advertise_responder: None,
44 }
45 }
46}
47
48impl TestProfileServer {
49 pub fn new(
58 service_definition: Option<bredr::ServiceDefinition>,
59 service_class_profile_id: Option<bredr::ServiceClassProfileIdentifier>,
60 ) -> TestProfileServerEndpoints {
61 let (proxy, stream) = fidl::endpoints::create_proxy_and_stream::<bredr::ProfileMarker>();
62
63 let mut client = match service_definition {
64 None => ProfileClient::new(proxy.clone()),
65 Some(service_definition) => {
66 let channel_params = fidl_bt::ChannelParameters::default();
67 ProfileClient::advertise(proxy.clone(), vec![service_definition], channel_params)
68 .expect("Failed to advertise.")
69 }
70 };
71
72 if let Some(service_class_profile_id) = service_class_profile_id {
73 client.add_search(service_class_profile_id, None).expect("Failed to search for peers.");
74 }
75
76 let test_server = TestProfileServer::from(stream);
77
78 TestProfileServerEndpoints { proxy, client, test_server }
79 }
80
81 pub async fn expect_search(&mut self) {
82 let request = self.profile_request_stream.next().await;
83 match request {
84 Some(Ok(bredr::ProfileRequest::Search { payload, .. })) => {
85 self.search_results_proxy = Some(payload.results.unwrap().into_proxy());
86 }
87 _ => panic!(
88 "unexpected result on profile request stream while waiting for search: {:?}",
89 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: {:?}",
105 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 {:?}, got {:?}", expected_channel, connection)
135 }
136 }
137
138 let (near_bt_channel, far_bt_channel) = bt::Channel::create();
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!("unexpected result on profile request stream: {:?}", request),
145 }
146 }
147
148 pub fn send_service_found(
149 &mut self,
150 peer_id: PeerId,
151 protocol_list: Option<Vec<bredr::ProtocolDescriptor>>,
152 attributes: Vec<bredr::Attribute>,
153 ) -> fidl::client::QueryResponseFut<()> {
154 let search_results_proxy = self.search_results_proxy.as_ref().expect("Search result proxy");
155 search_results_proxy.service_found(&peer_id.into(), protocol_list.as_deref(), &attributes)
156 }
157
158 pub fn send_connected(
159 &mut self,
160 peer_id: PeerId,
161 protocol_list: Vec<bredr::ProtocolDescriptor>,
162 ) -> bt::Channel {
163 let (near_bt_channel, far_bt_channel) = bt::Channel::create();
164 let far_bredr_channel: bredr::Channel =
165 far_bt_channel.try_into().expect("BT Channel into FIDL BREDR Channel");
166
167 let connection_receiver_proxy =
168 self.connection_receiver_proxy.as_ref().expect("Connection receiver proxy");
169 connection_receiver_proxy
170 .connected(&peer_id.into(), far_bredr_channel, &protocol_list)
171 .expect("Connected");
172
173 near_bt_channel
174 }
175}
176
177impl Stream for TestProfileServer {
179 type Item = Result<bredr::ProfileRequest, fidl::Error>;
180
181 fn poll_next(mut self: Pin<&mut Self>, context: &mut Context<'_>) -> Poll<Option<Self::Item>> {
182 let pinned_stream = Pin::new(&mut self.profile_request_stream);
183 pinned_stream.poll_next(context)
184 }
185}
186
187impl Drop for TestProfileServer {
188 fn drop(&mut self) {
189 if let Some(responder) = self.advertise_responder.take() {
191 responder
192 .send(Ok(&bredr::ProfileAdvertiseResponse::default()))
193 .expect("Drop responder");
194 }
195 }
196}