Skip to content

Commit df5ebb7

Browse files
Applied changes from review for embedded-io #101
1 parent 0cd9877 commit df5ebb7

File tree

2 files changed

+125
-48
lines changed

2 files changed

+125
-48
lines changed

src/common.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,27 @@ use std::{
2121
/// cloned instance of the mock can be used to check the expectations of the
2222
/// original instance that has been moved into a driver.
2323
#[derive(Debug, Clone)]
24-
pub struct Generic<T: Clone + Debug + PartialEq> {
24+
pub struct Generic<T: Clone + Debug + PartialEq, Data = ()> {
2525
expected: Arc<Mutex<VecDeque<T>>>,
2626
done_called: Arc<Mutex<DoneCallDetector>>,
27+
mock_data: Option<Data>,
2728
}
2829

29-
impl<'a, T: 'a> Generic<T>
30+
impl<'a, T: 'a, Data> Generic<T, Data>
3031
where
3132
T: Clone + Debug + PartialEq,
3233
{
3334
/// Create a new mock interface
3435
///
3536
/// This creates a new generic mock interface with initial expectations
36-
pub fn new<E>(expected: E) -> Generic<T>
37+
pub fn new<E>(expected: E) -> Generic<T, Data>
3738
where
3839
E: IntoIterator<Item = &'a T>,
3940
{
4041
let mut g = Generic {
4142
expected: Arc::new(Mutex::new(VecDeque::new())),
4243
done_called: Arc::new(Mutex::new(DoneCallDetector::new())),
44+
mock_data: None,
4345
};
4446

4547
g.update_expectations(expected);
@@ -99,10 +101,20 @@ where
99101
let e = self.expected.lock().unwrap();
100102
assert!(e.is_empty(), "Not all expectations consumed");
101103
}
104+
105+
/// Get the mock data
106+
pub fn mock_data(&self) -> &Option<Data> {
107+
&self.mock_data
108+
}
109+
110+
/// Set the mock data
111+
pub fn set_mock_data(&mut self, data: Option<Data>) {
112+
self.mock_data = data;
113+
}
102114
}
103115

104116
/// Iterator impl for use in mock impls
105-
impl<T> Iterator for Generic<T>
117+
impl<T, Data> Iterator for Generic<T, Data>
106118
where
107119
T: Clone + Debug + PartialEq,
108120
{

src/eh1/io.rs

Lines changed: 109 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -182,32 +182,40 @@ impl Transaction {
182182
}
183183

184184
/// Mock IO implementation
185-
pub type Mock = Generic<Transaction>;
185+
pub type Mock = Generic<Transaction, Vec<u8>>;
186186

187187
impl ErrorType for Mock {
188188
type Error = ErrorKind;
189189
}
190190

191191
impl Write for Mock {
192192
fn write(&mut self, buffer: &[u8]) -> Result<usize, Self::Error> {
193-
let w = self.next().expect("no expectation for io::write call");
194-
assert_eq!(w.expected_mode, Mode::Write, "io::write unexpected mode");
193+
let transaction = self.next().expect("no expectation for io::write call");
195194
assert_eq!(
196-
&w.expected_data, &buffer,
195+
transaction.expected_mode,
196+
Mode::Write,
197+
"io::write unexpected mode"
198+
);
199+
assert_eq!(
200+
&transaction.expected_data, &buffer,
197201
"io::write data does not match expectation"
198202
);
199203

200-
match w.expected_err {
204+
match transaction.expected_err {
201205
Some(err) => Err(err),
202206
None => Ok(buffer.len()),
203207
}
204208
}
205209

206210
fn flush(&mut self) -> Result<(), Self::Error> {
207-
let w = self.next().expect("no expectation for io::flush call");
208-
assert_eq!(w.expected_mode, Mode::Flush, "io::flush unexpected mode");
211+
let transaction = self.next().expect("no expectation for io::flush call");
212+
assert_eq!(
213+
transaction.expected_mode,
214+
Mode::Flush,
215+
"io::flush unexpected mode"
216+
);
209217

210-
match w.expected_err {
218+
match transaction.expected_err {
211219
Some(err) => Err(err),
212220
None => Ok(()),
213221
}
@@ -216,91 +224,116 @@ impl Write for Mock {
216224

217225
impl Read for Mock {
218226
fn read(&mut self, buffer: &mut [u8]) -> Result<usize, Self::Error> {
219-
let w = self.next().expect("no expectation for io::read call");
220-
assert_eq!(w.expected_mode, Mode::Read, "io::read unexpected mode");
221-
buffer.copy_from_slice(&w.response);
227+
let transaction = self.next().expect("no expectation for io::read call");
228+
assert_eq!(
229+
transaction.expected_mode,
230+
Mode::Read,
231+
"io::read unexpected mode"
232+
);
222233

223-
match w.expected_err {
234+
if transaction.response.len() > buffer.len() {
235+
panic!("response longer than read buffer for io::read");
236+
}
237+
238+
let len = std::cmp::min(buffer.len(), transaction.response.len());
239+
buffer[..len].copy_from_slice(&transaction.response[..len]);
240+
241+
match transaction.expected_err {
224242
Some(err) => Err(err),
225-
None => Ok(buffer.len()),
243+
None => Ok(len),
226244
}
227245
}
228246
}
229247

230248
impl Seek for Mock {
231249
fn seek(&mut self, pos: SeekFrom) -> Result<u64, Self::Error> {
232-
let w = self.next().expect("no expectation for io::seek call");
250+
let transaction = self.next().expect("no expectation for io::seek call");
233251

234-
if let Mode::Seek(expected_pos) = w.expected_mode {
252+
if let Mode::Seek(expected_pos) = transaction.expected_mode {
235253
assert_eq!(expected_pos, pos, "io::seek unexpected mode");
236254

237-
let ret_offset: u64 = u64::from_be_bytes(w.response.try_into().unwrap());
238-
match w.expected_err {
255+
let ret_offset: u64 = u64::from_be_bytes(transaction.response.try_into().unwrap());
256+
match transaction.expected_err {
239257
Some(err) => Err(err),
240258
None => Ok(ret_offset),
241259
}
242260
} else {
243-
panic!("unexpected seek mode");
261+
panic!(
262+
"expected seek transaction, but instead encountered {:?}. io::seek unexpected mode",
263+
transaction.expected_mode
264+
);
244265
}
245266
}
246267
}
247268

248269
impl WriteReady for Mock {
249270
fn write_ready(&mut self) -> Result<bool, Self::Error> {
250-
let w = self
271+
let transaction = self
251272
.next()
252273
.expect("no expectation for io::write_ready call");
253274

254-
match w.expected_mode {
255-
Mode::WriteReady(ready) if w.expected_err.is_none() => Ok(ready),
256-
Mode::WriteReady(_) if w.expected_err.is_some() => Err(w.expected_err.unwrap()),
257-
_ => panic!("unexpected write_ready mode"),
275+
match transaction.expected_mode {
276+
Mode::WriteReady(ready) if transaction.expected_err.is_none() => Ok(ready),
277+
Mode::WriteReady(_) if transaction.expected_err.is_some() => {
278+
Err(transaction.expected_err.unwrap())
279+
}
280+
_ => panic!(
281+
"expected write_ready transaction, but instead encountered {:?}. io::write_ready unexpected mode",
282+
transaction.expected_mode
283+
),
258284
}
259285
}
260286
}
261287

262288
impl ReadReady for Mock {
263289
fn read_ready(&mut self) -> Result<bool, Self::Error> {
264-
let w = self.next().expect("no expectation for io::read_ready call");
290+
let transaction = self.next().expect("no expectation for io::read_ready call");
265291

266-
match w.expected_mode {
267-
Mode::ReadReady(ready) if w.expected_err.is_none() => Ok(ready),
268-
Mode::ReadReady(_) if w.expected_err.is_some() => Err(w.expected_err.unwrap()),
269-
_ => panic!("unexpected read_ready mode"),
292+
match transaction.expected_mode {
293+
Mode::ReadReady(ready) if transaction.expected_err.is_none() => Ok(ready),
294+
Mode::ReadReady(_) if transaction.expected_err.is_some() => {
295+
Err(transaction.expected_err.unwrap())
296+
}
297+
_ => panic!(
298+
"expected read_ready transaction, but instead encountered {:?}. io::read_ready unexpected mode",
299+
transaction.expected_mode
300+
)
270301
}
271302
}
272303
}
273304

274305
impl BufRead for Mock {
275306
fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
276-
let w = self.next().expect("no expectation for io::fill_buf call");
307+
let transaction = self.next().expect("no expectation for io::fill_buf call");
277308
assert_eq!(
278-
w.expected_mode,
309+
transaction.expected_mode,
279310
Mode::FillBuff,
280311
"io::fill_buf unexpected mode"
281312
);
282313

283-
let response_vec = w.response;
314+
let response_vec = transaction.response;
315+
self.set_mock_data(Some(response_vec));
284316

285-
match w.expected_err {
317+
match transaction.expected_err {
286318
Some(err) => Err(err),
287-
288-
// SAFETY : This is a memory leak. This is done on purpose to allow for a return
289-
// of a slice (pointer) to the internal buffer, which doesn't exist in mock implementation.
290-
// This way, after each call, response is going to be put on the heap and ref is going to be returned, without freeing this memory.
291-
// For mocking purposes this should be an acceptable solution.
292-
None => Ok(Box::leak(response_vec.into_boxed_slice())),
319+
None => Ok(self.mock_data().as_ref().unwrap()),
293320
}
294321
}
295322

296323
fn consume(&mut self, amt: usize) {
297-
let w = self.next().expect("no expectation for io::consume call");
324+
let transaction = self.next().expect("no expectation for io::consume call");
298325

299-
match w.expected_mode {
300-
Mode::Consume(expected_amt) if w.expected_err.is_none() => {
326+
match transaction.expected_mode {
327+
Mode::Consume(expected_amt) if transaction.expected_err.is_none() => {
301328
assert_eq!(expected_amt, amt, "io::consume unexpected amount");
302329
}
303-
_ => panic!("unexpected consume mode"),
330+
Mode::Consume(_) if transaction.expected_err.is_some() => {
331+
panic!("io::consume can't expect an error. io::consume unexpected error");
332+
}
333+
_ => panic!(
334+
"expected consume transaction, but instead encountered {:?}. io::consume unexpected mode",
335+
transaction.expected_mode
336+
)
304337
}
305338
}
306339
}
@@ -401,6 +434,19 @@ mod test {
401434
io.done();
402435
}
403436

437+
#[test]
438+
fn test_io_mock_read_buffer_to_long() {
439+
let mut io = Mock::new(&[Transaction::read(vec![10])]);
440+
441+
let mut buffer = [0; 3];
442+
let ret = io.read(&mut buffer).unwrap();
443+
444+
assert_eq!(buffer, [10, 0, 0]);
445+
assert_eq!(ret, 1);
446+
447+
io.done();
448+
}
449+
404450
#[tokio::test]
405451
#[cfg(feature = "embedded-hal-async")]
406452
async fn test_async_io_mock_read() {
@@ -466,12 +512,17 @@ mod test {
466512

467513
#[test]
468514
fn test_io_mock_fill_buf() {
469-
let mut io = Mock::new(&[Transaction::fill_buf(vec![10])]);
515+
let mut io = Mock::new(&[
516+
Transaction::fill_buf(vec![10]),
517+
Transaction::fill_buf(vec![10, 20, 30]),
518+
]);
470519

471520
let ret = io.fill_buf().unwrap();
472-
473521
assert_eq!(ret, &[10]);
474522

523+
let ret = io.fill_buf().unwrap();
524+
assert_eq!(ret, &[10, 20, 30]);
525+
475526
io.done();
476527
}
477528

@@ -548,6 +599,20 @@ mod test {
548599
io.done();
549600
}
550601

602+
#[test]
603+
#[should_panic(expected = "response longer than read buffer for io::read")]
604+
fn test_io_mock_read_buffer_to_short() {
605+
let mut io = Mock::new(&[Transaction::read(vec![10, 20, 30])]);
606+
607+
let mut buffer = [0; 1];
608+
let ret = io.read(&mut buffer).unwrap();
609+
610+
assert_eq!(buffer, [10]);
611+
assert_eq!(ret, 1);
612+
613+
io.done();
614+
}
615+
551616
#[test]
552617
#[should_panic(expected = "io::seek unexpected mode")]
553618
fn test_io_mock_seek_err() {

0 commit comments

Comments
 (0)