xref: /aosp_15_r20/external/uwb/src/rust/uwb_core/src/uci/mock_uci_hal.rs (revision e0df40009cb5d71e642272d38ba1bb7ffccfce41)
1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use std::collections::VecDeque;
16 use std::sync::{Arc, Mutex};
17 use std::time::Duration;
18 
19 use async_trait::async_trait;
20 use log::error;
21 use tokio::sync::{mpsc, Notify};
22 use tokio::time::timeout;
23 
24 use crate::error::{Error, Result};
25 use crate::params::uci_packets::SessionId;
26 use crate::uci::command::UciCommand;
27 use crate::uci::uci_hal::{UciHal, UciHalPacket};
28 
29 /// The mock implementation of UciHal.
30 #[derive(Default, Clone)]
31 pub struct MockUciHal {
32     // Wrap inside Arc<Mutex<>> so that the MockUciHal.clone(s) refer to the same object.
33     packet_sender: Arc<Mutex<Option<mpsc::UnboundedSender<UciHalPacket>>>>,
34     expected_calls: Arc<Mutex<VecDeque<ExpectedCall>>>,
35     expect_call_consumed: Arc<Notify>,
36 }
37 
38 impl MockUciHal {
new() -> Self39     pub fn new() -> Self {
40         Default::default()
41     }
42 
expected_open(&mut self, packets: Option<Vec<UciHalPacket>>, out: Result<()>)43     pub fn expected_open(&mut self, packets: Option<Vec<UciHalPacket>>, out: Result<()>) {
44         self.expected_calls.lock().unwrap().push_back(ExpectedCall::Open { packets, out });
45     }
46 
expected_close(&mut self, out: Result<()>)47     pub fn expected_close(&mut self, out: Result<()>) {
48         self.expected_calls.lock().unwrap().push_back(ExpectedCall::Close { out });
49     }
50 
expected_send_command( &mut self, expected_cmd: UciCommand, packets: Vec<UciHalPacket>, out: Result<()>, )51     pub fn expected_send_command(
52         &mut self,
53         expected_cmd: UciCommand,
54         packets: Vec<UciHalPacket>,
55         out: Result<()>,
56     ) {
57         self.expected_calls.lock().unwrap().push_back(ExpectedCall::SendCommand {
58             expected_cmd,
59             packets,
60             out,
61         });
62     }
63 
expected_send_packet( &mut self, expected_packet_tx: UciHalPacket, inject_packets_rx: Vec<UciHalPacket>, out: Result<()>, )64     pub fn expected_send_packet(
65         &mut self,
66         expected_packet_tx: UciHalPacket,
67         inject_packets_rx: Vec<UciHalPacket>,
68         out: Result<()>,
69     ) {
70         self.expected_calls.lock().unwrap().push_back(ExpectedCall::SendPacket {
71             expected_packet_tx,
72             inject_packets_rx,
73             out,
74         });
75     }
76 
expected_notify_session_initialized( &mut self, expected_session_id: SessionId, out: Result<()>, )77     pub fn expected_notify_session_initialized(
78         &mut self,
79         expected_session_id: SessionId,
80         out: Result<()>,
81     ) {
82         self.expected_calls
83             .lock()
84             .unwrap()
85             .push_back(ExpectedCall::NotifySessionInitialized { expected_session_id, out });
86     }
87 
wait_expected_calls_done(&mut self) -> bool88     pub async fn wait_expected_calls_done(&mut self) -> bool {
89         while !self.expected_calls.lock().unwrap().is_empty() {
90             if timeout(Duration::from_secs(1), self.expect_call_consumed.notified()).await.is_err()
91             {
92                 return false;
93             }
94         }
95         true
96     }
97 
98     // Receive a UCI packet (eg: UCI DATA_MESSAGE_RCV), from UWBS to Host.
receive_packet(&mut self, packet: UciHalPacket) -> Result<()>99     pub fn receive_packet(&mut self, packet: UciHalPacket) -> Result<()> {
100         if let Some(ref ps) = *self.packet_sender.lock().unwrap() {
101             match ps.send(packet) {
102                 Ok(_) => Ok(()),
103                 Err(_) => Err(Error::Unknown),
104             }
105         } else {
106             error!("MockUciHal unable to Rx packet from HAL as channel closed");
107             Err(Error::MockUndefined)
108         }
109     }
110 }
111 
112 #[async_trait]
113 impl UciHal for MockUciHal {
open(&mut self, packet_sender: mpsc::UnboundedSender<UciHalPacket>) -> Result<()>114     async fn open(&mut self, packet_sender: mpsc::UnboundedSender<UciHalPacket>) -> Result<()> {
115         let mut expected_calls = self.expected_calls.lock().unwrap();
116         match expected_calls.pop_front() {
117             Some(ExpectedCall::Open { packets, out }) => {
118                 self.expect_call_consumed.notify_one();
119                 if let Some(packets) = packets {
120                     for msg in packets.into_iter() {
121                         let _ = packet_sender.send(msg);
122                     }
123                 }
124                 if out.is_ok() {
125                     self.packet_sender.lock().unwrap().replace(packet_sender);
126                 }
127                 out
128             }
129             Some(call) => {
130                 expected_calls.push_front(call);
131                 Err(Error::MockUndefined)
132             }
133             None => Err(Error::MockUndefined),
134         }
135     }
136 
close(&mut self) -> Result<()>137     async fn close(&mut self) -> Result<()> {
138         let mut expected_calls = self.expected_calls.lock().unwrap();
139         match expected_calls.pop_front() {
140             Some(ExpectedCall::Close { out }) => {
141                 self.expect_call_consumed.notify_one();
142                 if out.is_ok() {
143                     *self.packet_sender.lock().unwrap() = None;
144                 }
145                 out
146             }
147             Some(call) => {
148                 expected_calls.push_front(call);
149                 Err(Error::MockUndefined)
150             }
151             None => Err(Error::MockUndefined),
152         }
153     }
154 
send_command(&mut self, cmd: UciCommand) -> Result<()>155     async fn send_command(&mut self, cmd: UciCommand) -> Result<()> {
156         let mut expected_calls = self.expected_calls.lock().unwrap();
157         match expected_calls.pop_front() {
158             Some(ExpectedCall::SendCommand { expected_cmd, packets, out })
159                 if expected_cmd == cmd =>
160             {
161                 self.expect_call_consumed.notify_one();
162                 let mut packet_sender_opt = self.packet_sender.lock().unwrap();
163                 let packet_sender = packet_sender_opt.as_mut().unwrap();
164                 for msg in packets.into_iter() {
165                     let _ = packet_sender.send(msg);
166                 }
167                 out
168             }
169             Some(call) => {
170                 expected_calls.push_front(call);
171                 Err(Error::MockUndefined)
172             }
173             None => Err(Error::MockUndefined),
174         }
175     }
176 
send_packet(&mut self, packet_tx: UciHalPacket) -> Result<()>177     async fn send_packet(&mut self, packet_tx: UciHalPacket) -> Result<()> {
178         // send_packet() will be directly called for sending UCI Data packets.
179         let mut expected_calls = self.expected_calls.lock().unwrap();
180         match expected_calls.pop_front() {
181             Some(ExpectedCall::SendPacket { expected_packet_tx, inject_packets_rx, out })
182                 if expected_packet_tx == packet_tx =>
183             {
184                 self.expect_call_consumed.notify_one();
185                 let mut packet_sender_opt = self.packet_sender.lock().unwrap();
186                 let packet_sender = packet_sender_opt.as_mut().unwrap();
187                 for msg in inject_packets_rx.into_iter() {
188                     let _ = packet_sender.send(msg);
189                 }
190                 out
191             }
192             Some(call) => {
193                 expected_calls.push_front(call);
194                 Err(Error::MockUndefined)
195             }
196             None => Err(Error::MockUndefined),
197         }
198     }
199 
notify_session_initialized(&mut self, session_id: SessionId) -> Result<()>200     async fn notify_session_initialized(&mut self, session_id: SessionId) -> Result<()> {
201         let mut expected_calls = self.expected_calls.lock().unwrap();
202         match expected_calls.pop_front() {
203             Some(ExpectedCall::NotifySessionInitialized { expected_session_id, out })
204                 if expected_session_id == session_id =>
205             {
206                 self.expect_call_consumed.notify_one();
207                 out
208             }
209             Some(call) => {
210                 expected_calls.push_front(call);
211                 Err(Error::MockUndefined)
212             }
213             None => Err(Error::MockUndefined),
214         }
215     }
216 }
217 
218 enum ExpectedCall {
219     Open {
220         packets: Option<Vec<UciHalPacket>>,
221         out: Result<()>,
222     },
223     Close {
224         out: Result<()>,
225     },
226     SendCommand {
227         expected_cmd: UciCommand,
228         packets: Vec<UciHalPacket>,
229         out: Result<()>,
230     },
231     SendPacket {
232         expected_packet_tx: UciHalPacket,
233         inject_packets_rx: Vec<UciHalPacket>,
234         out: Result<()>,
235     },
236     NotifySessionInitialized {
237         expected_session_id: SessionId,
238         out: Result<()>,
239     },
240 }
241