Skip to content

Commit 190b09f

Browse files
committed
mock SPI errors
1 parent e11348e commit 190b09f

File tree

1 file changed

+147
-9
lines changed

1 file changed

+147
-9
lines changed

src/eh1/spi.rs

Lines changed: 147 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,37 @@
3838
//! spi.transfer_in_place(&mut buf).unwrap();
3939
//! assert_eq!(buf, vec![5, 6]);
4040
//!
41-
//! // Finalise expectations
41+
//! // Finalize expectations
42+
//! spi.done();
43+
//! ```
44+
//!
45+
//! ## Mocking Errors
46+
//!
47+
//! ```
48+
//! # use eh1 as embedded_hal;
49+
//! use embedded_hal::spi::{SpiBus, SpiDevice, ErrorKind};
50+
//! use embedded_hal_mock::eh1::spi::{Mock as SpiMock, Transaction as SpiTransaction};
51+
//! use embedded_hal_nb::{nb::Error, spi::FullDuplex};
52+
//!
53+
//! // Configure expectations
54+
//! let expectations = [
55+
//! SpiTransaction::write(0x09).with_error(ErrorKind::Other),
56+
//! SpiTransaction::transfer_in_place(vec![3, 4], vec![5, 6]).with_error(ErrorKind::Other),
57+
//! SpiTransaction::transaction_start().with_error(ErrorKind::Other),
58+
//! ];
59+
//!
60+
//! let mut spi = SpiMock::new(&expectations);
61+
//! // FullDuplex transfers
62+
//! assert_eq!(FullDuplex::write(&mut spi, 0x09), Err(Error::Other(ErrorKind::Other)));
63+
//!
64+
//! // Transferring
65+
//! let mut buf = vec![3, 4];
66+
//! assert_eq!(SpiBus::transfer_in_place(&mut spi, &mut buf), Err(ErrorKind::Other));
67+
//!
68+
//! // SpiDevice transfer that fails to start
69+
//! assert_eq!(SpiDevice::write(&mut spi, &vec![7, 8]), Err(ErrorKind::Other));
70+
//!
71+
//! // Finalize expectations
4272
//! spi.done();
4373
//! ```
4474
use core::fmt::Debug;
@@ -77,6 +107,7 @@ pub struct Transaction<W> {
77107
expected_mode: Mode,
78108
expected_data: Vec<W>,
79109
response: Vec<W>,
110+
err: Option<spi::ErrorKind>,
80111
}
81112

82113
impl<W> Transaction<W>
@@ -89,6 +120,7 @@ where
89120
expected_mode: Mode::Write,
90121
expected_data: expected,
91122
response: Vec::new(),
123+
err: None,
92124
}
93125
}
94126

@@ -98,6 +130,7 @@ where
98130
expected_mode: Mode::Transfer,
99131
expected_data: expected,
100132
response,
133+
err: None,
101134
}
102135
}
103136

@@ -107,6 +140,7 @@ where
107140
expected_mode: Mode::TransferInplace,
108141
expected_data: expected,
109142
response,
143+
err: None,
110144
}
111145
}
112146

@@ -116,6 +150,7 @@ where
116150
expected_mode: Mode::Write,
117151
expected_data: [expected].to_vec(),
118152
response: Vec::new(),
153+
err: None,
119154
}
120155
}
121156

@@ -125,6 +160,7 @@ where
125160
expected_mode: Mode::Read,
126161
expected_data: Vec::new(),
127162
response: [response].to_vec(),
163+
err: None,
128164
}
129165
}
130166

@@ -134,6 +170,7 @@ where
134170
expected_mode: Mode::Read,
135171
expected_data: Vec::new(),
136172
response,
173+
err: None,
137174
}
138175
}
139176

@@ -143,6 +180,7 @@ where
143180
expected_mode: Mode::Flush,
144181
expected_data: Vec::new(),
145182
response: Vec::new(),
183+
err: None,
146184
}
147185
}
148186

@@ -152,6 +190,7 @@ where
152190
expected_mode: Mode::TransactionStart,
153191
expected_data: Vec::new(),
154192
response: Vec::new(),
193+
err: None,
155194
}
156195
}
157196

@@ -161,6 +200,7 @@ where
161200
expected_mode: Mode::TransactionEnd,
162201
expected_data: Vec::new(),
163202
response: Vec::new(),
203+
err: None,
164204
}
165205
}
166206

@@ -170,6 +210,17 @@ where
170210
expected_mode: Mode::Delay(delay),
171211
expected_data: Vec::new(),
172212
response: Vec::new(),
213+
err: None,
214+
}
215+
}
216+
217+
/// Add an error return to a transaction
218+
///
219+
/// This is used to mock hardware failures.
220+
pub fn with_error(self, error: spi::ErrorKind) -> Self {
221+
Self {
222+
err: Some(error),
223+
..self
173224
}
174225
}
175226
}
@@ -230,7 +281,10 @@ where
230281
"spi:read mismatched response length"
231282
);
232283
buffer.copy_from_slice(&w.response);
233-
Ok(())
284+
match w.err {
285+
Some(err) => Err(err),
286+
None => Ok(()),
287+
}
234288
}
235289

236290
/// spi::Write implementation for Mock
@@ -243,7 +297,10 @@ where
243297
&w.expected_data, &buffer,
244298
"spi::write data does not match expectation"
245299
);
246-
Ok(())
300+
match w.err {
301+
Some(err) => Err(err),
302+
None => Ok(()),
303+
}
247304
}
248305

249306
fn transfer(&mut self, read: &mut [W], write: &[W]) -> Result<(), Self::Error> {
@@ -263,7 +320,10 @@ where
263320
"mismatched response length for spi::transfer"
264321
);
265322
read.copy_from_slice(&w.response);
266-
Ok(())
323+
match w.err {
324+
Some(err) => Err(err),
325+
None => Ok(()),
326+
}
267327
}
268328

269329
/// spi::TransferInplace implementation for Mock
@@ -288,7 +348,10 @@ where
288348
"mismatched response length for spi::transfer_in_place"
289349
);
290350
buffer.copy_from_slice(&w.response);
291-
Ok(())
351+
match w.err {
352+
Some(err) => Err(err),
353+
None => Ok(()),
354+
}
292355
}
293356

294357
fn flush(&mut self) -> Result<(), Self::Error> {
@@ -345,7 +408,10 @@ where
345408
data.expected_data[0], buffer,
346409
"spi::write data does not match expectation"
347410
);
348-
Ok(())
411+
match data.err {
412+
Some(err) => Err(embedded_hal_nb::nb::Error::Other(err)),
413+
None => Ok(()),
414+
}
349415
}
350416

351417
/// spi::FullDuplex implementation for Mock
@@ -360,7 +426,10 @@ where
360426
"mismatched response length for spi::read"
361427
);
362428
let buffer: W = w.response[0];
363-
Ok(buffer)
429+
match w.err {
430+
Some(err) => Err(embedded_hal_nb::nb::Error::Other(err)),
431+
None => Ok(buffer),
432+
}
364433
}
365434
}
366435

@@ -380,7 +449,9 @@ where
380449
Mode::TransactionStart,
381450
"spi::transaction unexpected mode"
382451
);
383-
452+
if let Some(err) = w.err {
453+
return Err(err);
454+
}
384455
for op in operations {
385456
match op {
386457
Operation::Read(buffer) => {
@@ -415,7 +486,10 @@ where
415486
"spi::transaction unexpected mode"
416487
);
417488

418-
Ok(())
489+
match w.err {
490+
Some(err) => Err(err),
491+
None => Ok(()),
492+
}
419493
}
420494
}
421495

@@ -561,6 +635,70 @@ mod test {
561635
spi.done();
562636
}
563637

638+
#[test]
639+
fn test_spi_mock_bus_error() {
640+
use eh1::spi::SpiBus;
641+
642+
let expectations = [
643+
Transaction::write_vec(vec![1, 2]).with_error(spi::ErrorKind::Other),
644+
Transaction::write(9).with_error(spi::ErrorKind::Other),
645+
Transaction::read(10).with_error(spi::ErrorKind::Other),
646+
Transaction::write(0xFE).with_error(spi::ErrorKind::Other),
647+
Transaction::read(0xFF).with_error(spi::ErrorKind::Other),
648+
Transaction::transfer_in_place(vec![3, 4], vec![5, 6])
649+
.with_error(spi::ErrorKind::Other),
650+
];
651+
let mut spi = Mock::new(&expectations);
652+
653+
assert_eq!(SpiBus::write(&mut spi, &[1, 2]), Err(spi::ErrorKind::Other));
654+
assert_eq!(SpiBus::write(&mut spi, &[0x09]), Err(spi::ErrorKind::Other));
655+
assert_eq!(
656+
FullDuplex::read(&mut spi),
657+
Err(embedded_hal_nb::nb::Error::Other(spi::ErrorKind::Other))
658+
);
659+
assert_eq!(SpiBus::write(&mut spi, &[0xfe]), Err(spi::ErrorKind::Other));
660+
assert_eq!(
661+
FullDuplex::read(&mut spi),
662+
Err(embedded_hal_nb::nb::Error::Other(spi::ErrorKind::Other))
663+
);
664+
let mut v = vec![3, 4];
665+
assert_eq!(
666+
SpiBus::transfer_in_place(&mut spi, &mut v),
667+
Err(spi::ErrorKind::Other)
668+
);
669+
670+
spi.done();
671+
}
672+
673+
#[test]
674+
fn test_spi_mock_device_error() {
675+
use eh1::spi::SpiDevice;
676+
677+
let expectations = [
678+
Transaction::transaction_start().with_error(spi::ErrorKind::Other),
679+
Transaction::transaction_start(),
680+
Transaction::transfer_in_place(vec![3, 4], vec![5, 6]),
681+
Transaction::transaction_end().with_error(spi::ErrorKind::Other),
682+
];
683+
let mut spi = Mock::new(&expectations);
684+
685+
let mut v = vec![3, 4];
686+
687+
// exits early due to returned error on transaction start
688+
assert_eq!(
689+
SpiDevice::transfer_in_place(&mut spi, &mut v),
690+
Err(spi::ErrorKind::Other)
691+
);
692+
// transfers successfully, but transaction_end() results in error
693+
assert_eq!(
694+
SpiDevice::transfer_in_place(&mut spi, &mut v),
695+
Err(spi::ErrorKind::Other)
696+
);
697+
assert_eq!(v, vec![5, 6]);
698+
699+
spi.done();
700+
}
701+
564702
#[test]
565703
fn test_spi_mock_multiple1() {
566704
use eh1::spi::SpiBus;

0 commit comments

Comments
 (0)