• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 tokio::sync::{mpsc, Notify};
21 use tokio::time::timeout;
22 
23 use crate::error::{Error, Result};
24 use crate::params::uci_packets::SessionId;
25 use crate::uci::command::UciCommand;
26 use crate::uci::uci_hal::{UciHal, UciHalPacket};
27 
28 /// The mock implementation of UciHal.
29 #[derive(Default, Clone)]
30 pub struct MockUciHal {
31     packet_sender: Option<mpsc::UnboundedSender<UciHalPacket>>,
32     expected_calls: Arc<Mutex<VecDeque<ExpectedCall>>>,
33     expect_call_consumed: Arc<Notify>,
34 }
35 
36 impl MockUciHal {
new() -> Self37     pub fn new() -> Self {
38         Default::default()
39     }
40 
expected_open(&mut self, packets: Option<Vec<UciHalPacket>>, out: Result<()>)41     pub fn expected_open(&mut self, packets: Option<Vec<UciHalPacket>>, out: Result<()>) {
42         self.expected_calls.lock().unwrap().push_back(ExpectedCall::Open { packets, out });
43     }
44 
expected_close(&mut self, out: Result<()>)45     pub fn expected_close(&mut self, out: Result<()>) {
46         self.expected_calls.lock().unwrap().push_back(ExpectedCall::Close { out });
47     }
48 
expected_send_command( &mut self, expected_cmd: UciCommand, packets: Vec<UciHalPacket>, out: Result<()>, )49     pub fn expected_send_command(
50         &mut self,
51         expected_cmd: UciCommand,
52         packets: Vec<UciHalPacket>,
53         out: Result<()>,
54     ) {
55         self.expected_calls.lock().unwrap().push_back(ExpectedCall::SendCommand {
56             expected_cmd,
57             packets,
58             out,
59         });
60     }
61 
expected_send_packet( &mut self, expected_packet_tx: UciHalPacket, inject_packets_rx: Vec<UciHalPacket>, out: Result<()>, )62     pub fn expected_send_packet(
63         &mut self,
64         expected_packet_tx: UciHalPacket,
65         inject_packets_rx: Vec<UciHalPacket>,
66         out: Result<()>,
67     ) {
68         self.expected_calls.lock().unwrap().push_back(ExpectedCall::SendPacket {
69             expected_packet_tx,
70             inject_packets_rx,
71             out,
72         });
73     }
74 
expected_notify_session_initialized( &mut self, expected_session_id: SessionId, out: Result<()>, )75     pub fn expected_notify_session_initialized(
76         &mut self,
77         expected_session_id: SessionId,
78         out: Result<()>,
79     ) {
80         self.expected_calls
81             .lock()
82             .unwrap()
83             .push_back(ExpectedCall::NotifySessionInitialized { expected_session_id, out });
84     }
85 
wait_expected_calls_done(&mut self) -> bool86     pub async fn wait_expected_calls_done(&mut self) -> bool {
87         while !self.expected_calls.lock().unwrap().is_empty() {
88             if timeout(Duration::from_secs(1), self.expect_call_consumed.notified()).await.is_err()
89             {
90                 return false;
91             }
92         }
93         true
94     }
95 }
96 
97 #[async_trait]
98 impl UciHal for MockUciHal {
open(&mut self, packet_sender: mpsc::UnboundedSender<UciHalPacket>) -> Result<()>99     async fn open(&mut self, packet_sender: mpsc::UnboundedSender<UciHalPacket>) -> Result<()> {
100         let mut expected_calls = self.expected_calls.lock().unwrap();
101         match expected_calls.pop_front() {
102             Some(ExpectedCall::Open { packets, out }) => {
103                 self.expect_call_consumed.notify_one();
104                 if let Some(packets) = packets {
105                     for msg in packets.into_iter() {
106                         let _ = packet_sender.send(msg);
107                     }
108                 }
109                 if out.is_ok() {
110                     self.packet_sender.replace(packet_sender);
111                 }
112                 out
113             }
114             Some(call) => {
115                 expected_calls.push_front(call);
116                 Err(Error::MockUndefined)
117             }
118             None => Err(Error::MockUndefined),
119         }
120     }
121 
close(&mut self) -> Result<()>122     async fn close(&mut self) -> Result<()> {
123         let mut expected_calls = self.expected_calls.lock().unwrap();
124         match expected_calls.pop_front() {
125             Some(ExpectedCall::Close { out }) => {
126                 self.expect_call_consumed.notify_one();
127                 if out.is_ok() {
128                     self.packet_sender = None;
129                 }
130                 out
131             }
132             Some(call) => {
133                 expected_calls.push_front(call);
134                 Err(Error::MockUndefined)
135             }
136             None => Err(Error::MockUndefined),
137         }
138     }
139 
send_command(&mut self, cmd: UciCommand) -> Result<()>140     async fn send_command(&mut self, cmd: UciCommand) -> Result<()> {
141         let mut expected_calls = self.expected_calls.lock().unwrap();
142         match expected_calls.pop_front() {
143             Some(ExpectedCall::SendCommand { expected_cmd, packets, out })
144                 if expected_cmd == cmd =>
145             {
146                 self.expect_call_consumed.notify_one();
147                 let packet_sender = self.packet_sender.as_mut().unwrap();
148                 for msg in packets.into_iter() {
149                     let _ = packet_sender.send(msg);
150                 }
151                 out
152             }
153             Some(call) => {
154                 expected_calls.push_front(call);
155                 Err(Error::MockUndefined)
156             }
157             None => Err(Error::MockUndefined),
158         }
159     }
160 
send_packet(&mut self, packet_tx: UciHalPacket) -> Result<()>161     async fn send_packet(&mut self, packet_tx: UciHalPacket) -> Result<()> {
162         // send_packet() will be directly called for sending UCI Data packets.
163         let mut expected_calls = self.expected_calls.lock().unwrap();
164         match expected_calls.pop_front() {
165             Some(ExpectedCall::SendPacket { expected_packet_tx, inject_packets_rx, out })
166                 if expected_packet_tx == packet_tx =>
167             {
168                 self.expect_call_consumed.notify_one();
169                 let packet_sender = self.packet_sender.as_mut().unwrap();
170                 for msg in inject_packets_rx.into_iter() {
171                     let _ = packet_sender.send(msg);
172                 }
173                 out
174             }
175             Some(call) => {
176                 expected_calls.push_front(call);
177                 Err(Error::MockUndefined)
178             }
179             None => Err(Error::MockUndefined),
180         }
181     }
182 
notify_session_initialized(&mut self, session_id: SessionId) -> Result<()>183     async fn notify_session_initialized(&mut self, session_id: SessionId) -> Result<()> {
184         let mut expected_calls = self.expected_calls.lock().unwrap();
185         match expected_calls.pop_front() {
186             Some(ExpectedCall::NotifySessionInitialized { expected_session_id, out })
187                 if expected_session_id == session_id =>
188             {
189                 self.expect_call_consumed.notify_one();
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 }
200 
201 enum ExpectedCall {
202     Open {
203         packets: Option<Vec<UciHalPacket>>,
204         out: Result<()>,
205     },
206     Close {
207         out: Result<()>,
208     },
209     SendCommand {
210         expected_cmd: UciCommand,
211         packets: Vec<UciHalPacket>,
212         out: Result<()>,
213     },
214     SendPacket {
215         expected_packet_tx: UciHalPacket,
216         inject_packets_rx: Vec<UciHalPacket>,
217         out: Result<()>,
218     },
219     NotifySessionInitialized {
220         expected_session_id: SessionId,
221         out: Result<()>,
222     },
223 }
224