• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //! MockUwbAdaptation
18 
19 use crate::adaptation::UwbAdaptation;
20 use crate::error::UwbErr;
21 use crate::uci::uci_hrcv;
22 use crate::uci::HalCallback;
23 use android_hardware_uwb::aidl::android::hardware::uwb::{
24     UwbEvent::UwbEvent, UwbStatus::UwbStatus,
25 };
26 use async_trait::async_trait;
27 use log::warn;
28 use std::collections::VecDeque;
29 use std::sync::Mutex as StdMutex;
30 use tokio::sync::mpsc;
31 use uwb_uci_packets::{Packet, UciCommandPacket};
32 
33 type Result<T> = std::result::Result<T, UwbErr>;
34 
35 #[cfg(any(test, fuzzing))]
36 enum ExpectedCall {
37     Finalize {
38         expected_exit_status: bool,
39     },
40     HalOpen {
41         out: Result<()>,
42     },
43     HalClose {
44         out: Result<()>,
45     },
46     CoreInitialization {
47         out: Result<()>,
48     },
49     SessionInitialization {
50         expected_session_id: i32,
51         out: Result<()>,
52     },
53     SendUciMessage {
54         expected_cmd: UciCommandPacket,
55         rsp: Option<uci_hrcv::UciResponse>,
56         notf: Option<uci_hrcv::UciNotification>,
57         out: Result<()>,
58     },
59 }
60 
61 #[cfg(any(test, fuzzing))]
62 pub struct MockUwbAdaptation {
63     rsp_sender: mpsc::UnboundedSender<HalCallback>,
64     expected_calls: StdMutex<VecDeque<ExpectedCall>>,
65 }
66 
67 #[cfg(any(test, fuzzing))]
68 impl MockUwbAdaptation {
new(rsp_sender: mpsc::UnboundedSender<HalCallback>) -> Self69     pub fn new(rsp_sender: mpsc::UnboundedSender<HalCallback>) -> Self {
70         Self { rsp_sender, expected_calls: StdMutex::new(VecDeque::new()) }
71     }
72 
expect_finalize(&self, expected_exit_status: bool)73     pub fn expect_finalize(&self, expected_exit_status: bool) {
74         self.expected_calls
75             .lock()
76             .unwrap()
77             .push_back(ExpectedCall::Finalize { expected_exit_status });
78     }
expect_hal_open(&self, out: Result<()>)79     pub fn expect_hal_open(&self, out: Result<()>) {
80         self.expected_calls.lock().unwrap().push_back(ExpectedCall::HalOpen { out });
81     }
expect_hal_close(&self, out: Result<()>)82     pub fn expect_hal_close(&self, out: Result<()>) {
83         self.expected_calls.lock().unwrap().push_back(ExpectedCall::HalClose { out });
84     }
expect_core_initialization(&self, out: Result<()>)85     pub fn expect_core_initialization(&self, out: Result<()>) {
86         self.expected_calls.lock().unwrap().push_back(ExpectedCall::CoreInitialization { out });
87     }
expect_session_initialization(&self, expected_session_id: i32, out: Result<()>)88     pub fn expect_session_initialization(&self, expected_session_id: i32, out: Result<()>) {
89         self.expected_calls
90             .lock()
91             .unwrap()
92             .push_back(ExpectedCall::SessionInitialization { expected_session_id, out });
93     }
expect_send_uci_message( &self, expected_cmd: UciCommandPacket, rsp: Option<uci_hrcv::UciResponse>, notf: Option<uci_hrcv::UciNotification>, out: Result<()>, )94     pub fn expect_send_uci_message(
95         &self,
96         expected_cmd: UciCommandPacket,
97         rsp: Option<uci_hrcv::UciResponse>,
98         notf: Option<uci_hrcv::UciNotification>,
99         out: Result<()>,
100     ) {
101         self.expected_calls.lock().unwrap().push_back(ExpectedCall::SendUciMessage {
102             expected_cmd,
103             rsp,
104             notf,
105             out,
106         });
107     }
108 
clear_expected_calls(&self)109     pub fn clear_expected_calls(&self) {
110         self.expected_calls.lock().unwrap().clear();
111     }
112 
send_hal_event(&self, event: UwbEvent, event_status: UwbStatus)113     async fn send_hal_event(&self, event: UwbEvent, event_status: UwbStatus) {
114         self.rsp_sender.send(HalCallback::Event { event, event_status }).unwrap();
115     }
116 
send_uci_response(&self, rsp: uci_hrcv::UciResponse)117     async fn send_uci_response(&self, rsp: uci_hrcv::UciResponse) {
118         self.rsp_sender.send(HalCallback::UciRsp(rsp)).unwrap();
119     }
120 
send_uci_notification(&self, ntf: uci_hrcv::UciNotification)121     async fn send_uci_notification(&self, ntf: uci_hrcv::UciNotification) {
122         self.rsp_sender.send(HalCallback::UciNtf(ntf)).unwrap();
123     }
124 }
125 
126 #[cfg(any(test, fuzzing))]
127 impl Drop for MockUwbAdaptation {
drop(&mut self)128     fn drop(&mut self) {
129         assert!(self.expected_calls.lock().unwrap().is_empty());
130     }
131 }
132 
133 #[cfg(any(test, fuzzing))]
134 #[async_trait]
135 impl UwbAdaptation for MockUwbAdaptation {
finalize(&mut self, exit_status: bool)136     async fn finalize(&mut self, exit_status: bool) {
137         let mut expected_calls = self.expected_calls.lock().unwrap();
138         match expected_calls.pop_front() {
139             Some(ExpectedCall::Finalize { expected_exit_status })
140                 if expected_exit_status == exit_status =>
141             {
142                 return;
143             }
144             Some(call) => {
145                 expected_calls.push_front(call);
146             }
147             None => {}
148         }
149         warn!("unpected finalize() called");
150     }
151 
hal_open(&self) -> Result<()>152     async fn hal_open(&self) -> Result<()> {
153         let expected_out = {
154             let mut expected_calls = self.expected_calls.lock().unwrap();
155             match expected_calls.pop_front() {
156                 Some(ExpectedCall::HalOpen { out }) => Some(out),
157                 Some(call) => {
158                     expected_calls.push_front(call);
159                     None
160                 }
161                 None => None,
162             }
163         };
164 
165         match expected_out {
166             Some(out) => {
167                 let status = if out.is_ok() { UwbStatus::OK } else { UwbStatus::FAILED };
168                 self.send_hal_event(UwbEvent::OPEN_CPLT, status).await;
169                 out
170             }
171             None => {
172                 warn!("unpected hal_open() called");
173                 Err(UwbErr::Undefined)
174             }
175         }
176     }
177 
hal_close(&self) -> Result<()>178     async fn hal_close(&self) -> Result<()> {
179         let expected_out = {
180             let mut expected_calls = self.expected_calls.lock().unwrap();
181             match expected_calls.pop_front() {
182                 Some(ExpectedCall::HalClose { out }) => Some(out),
183                 Some(call) => {
184                     expected_calls.push_front(call);
185                     None
186                 }
187                 None => None,
188             }
189         };
190 
191         match expected_out {
192             Some(out) => {
193                 let status = if out.is_ok() { UwbStatus::OK } else { UwbStatus::FAILED };
194                 self.send_hal_event(UwbEvent::CLOSE_CPLT, status).await;
195                 out
196             }
197             None => {
198                 warn!("unpected hal_close() called");
199                 Err(UwbErr::Undefined)
200             }
201         }
202     }
203 
core_initialization(&self) -> Result<()>204     async fn core_initialization(&self) -> Result<()> {
205         let expected_out = {
206             let mut expected_calls = self.expected_calls.lock().unwrap();
207             match expected_calls.pop_front() {
208                 Some(ExpectedCall::CoreInitialization { out }) => Some(out),
209                 Some(call) => {
210                     expected_calls.push_front(call);
211                     None
212                 }
213                 None => None,
214             }
215         };
216 
217         match expected_out {
218             Some(out) => {
219                 let status = if out.is_ok() { UwbStatus::OK } else { UwbStatus::FAILED };
220                 self.send_hal_event(UwbEvent::POST_INIT_CPLT, status).await;
221                 out
222             }
223             None => {
224                 warn!("unpected core_initialization() called");
225                 Err(UwbErr::Undefined)
226             }
227         }
228     }
229 
session_initialization(&self, session_id: i32) -> Result<()>230     async fn session_initialization(&self, session_id: i32) -> Result<()> {
231         let expected_out = {
232             let mut expected_calls = self.expected_calls.lock().unwrap();
233             match expected_calls.pop_front() {
234                 Some(ExpectedCall::SessionInitialization { expected_session_id, out })
235                     if expected_session_id == session_id =>
236                 {
237                     Some(out)
238                 }
239                 Some(call) => {
240                     expected_calls.push_front(call);
241                     None
242                 }
243                 None => None,
244             }
245         };
246 
247         match expected_out {
248             Some(out) => out,
249             None => {
250                 warn!("unpected session_initialization() called");
251                 Err(UwbErr::Undefined)
252             }
253         }
254     }
255 
send_uci_message(&self, cmd: UciCommandPacket) -> Result<()>256     async fn send_uci_message(&self, cmd: UciCommandPacket) -> Result<()> {
257         let expected_out = {
258             let mut expected_calls = self.expected_calls.lock().unwrap();
259             match expected_calls.pop_front() {
260                 Some(ExpectedCall::SendUciMessage {
261                     expected_cmd,
262                     rsp,
263                     notf,
264                     out,
265                     // PDL generated packets do not implement PartialEq, so use the raw bytes for comparison.
266                 }) if expected_cmd.clone().to_bytes() == cmd.to_bytes() => Some((rsp, notf, out)),
267                 Some(call) => {
268                     expected_calls.push_front(call);
269                     None
270                 }
271                 None => None,
272             }
273         };
274 
275         match expected_out {
276             Some((rsp, notf, out)) => {
277                 if let Some(notf) = notf {
278                     self.send_uci_notification(notf).await;
279                 }
280                 if let Some(rsp) = rsp {
281                     self.send_uci_response(rsp).await;
282                 }
283                 out
284             }
285             None => {
286                 warn!("unpected send_uci_message() called");
287                 Err(UwbErr::Undefined)
288             }
289         }
290     }
291 }
292