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//! ```
4474use 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
82113impl < W > Transaction < W >
89120 expected_mode : Mode :: Write ,
90121 expected_data : expected,
91122 response : Vec :: new ( ) ,
123+ err : None ,
92124 }
93125 }
94126
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}
@@ -207,7 +258,10 @@ where
207258 "spi:read mismatched response length"
208259 ) ;
209260 buffer. copy_from_slice ( & w. response ) ;
210- Ok ( ( ) )
261+ match w. err {
262+ Some ( err) => Err ( err) ,
263+ None => Ok ( ( ) ) ,
264+ }
211265 }
212266
213267 /// spi::Write implementation for Mock
@@ -220,7 +274,10 @@ where
220274 & w. expected_data, & buffer,
221275 "spi::write data does not match expectation"
222276 ) ;
223- Ok ( ( ) )
277+ match w. err {
278+ Some ( err) => Err ( err) ,
279+ None => Ok ( ( ) ) ,
280+ }
224281 }
225282
226283 fn transfer ( & mut self , read : & mut [ W ] , write : & [ W ] ) -> Result < ( ) , Self :: Error > {
@@ -240,7 +297,10 @@ where
240297 "mismatched response length for spi::transfer"
241298 ) ;
242299 read. copy_from_slice ( & w. response ) ;
243- Ok ( ( ) )
300+ match w. err {
301+ Some ( err) => Err ( err) ,
302+ None => Ok ( ( ) ) ,
303+ }
244304 }
245305
246306 /// spi::TransferInplace implementation for Mock
@@ -265,7 +325,10 @@ where
265325 "mismatched response length for spi::transfer_in_place"
266326 ) ;
267327 buffer. copy_from_slice ( & w. response ) ;
268- Ok ( ( ) )
328+ match w. err {
329+ Some ( err) => Err ( err) ,
330+ None => Ok ( ( ) ) ,
331+ }
269332 }
270333
271334 fn flush ( & mut self ) -> Result < ( ) , Self :: Error > {
@@ -322,7 +385,10 @@ where
322385 data. expected_data[ 0 ] , buffer,
323386 "spi::write data does not match expectation"
324387 ) ;
325- Ok ( ( ) )
388+ match data. err {
389+ Some ( err) => Err ( nb:: Error :: Other ( err) ) ,
390+ None => Ok ( ( ) ) ,
391+ }
326392 }
327393
328394 /// spi::FullDuplex implementation for Mock
@@ -337,7 +403,10 @@ where
337403 "mismatched response length for spi::read"
338404 ) ;
339405 let buffer: W = w. response [ 0 ] ;
340- Ok ( buffer)
406+ match w. err {
407+ Some ( err) => Err ( nb:: Error :: Other ( err) ) ,
408+ None => Ok ( buffer) ,
409+ }
341410 }
342411}
343412
@@ -357,7 +426,9 @@ where
357426 Mode :: TransactionStart ,
358427 "spi::transaction unexpected mode"
359428 ) ;
360-
429+ if let Some ( err) = w. err {
430+ return Err ( err) ;
431+ }
361432 for op in operations {
362433 match op {
363434 Operation :: Read ( buffer) => {
@@ -392,7 +463,10 @@ where
392463 "spi::transaction unexpected mode"
393464 ) ;
394465
395- Ok ( ( ) )
466+ match w. err {
467+ Some ( err) => Err ( err) ,
468+ None => Ok ( ( ) ) ,
469+ }
396470 }
397471}
398472
@@ -538,6 +612,70 @@ mod test {
538612 spi. done ( ) ;
539613 }
540614
615+ #[ test]
616+ fn test_spi_mock_bus_error ( ) {
617+ use eh1:: spi:: SpiBus ;
618+
619+ let expectations = [
620+ Transaction :: write_vec ( vec ! [ 1 , 2 ] ) . with_error ( spi:: ErrorKind :: Other ) ,
621+ Transaction :: write ( 9 ) . with_error ( spi:: ErrorKind :: Other ) ,
622+ Transaction :: read ( 10 ) . with_error ( spi:: ErrorKind :: Other ) ,
623+ Transaction :: write ( 0xFE ) . with_error ( spi:: ErrorKind :: Other ) ,
624+ Transaction :: read ( 0xFF ) . with_error ( spi:: ErrorKind :: Other ) ,
625+ Transaction :: transfer_in_place ( vec ! [ 3 , 4 ] , vec ! [ 5 , 6 ] )
626+ . with_error ( spi:: ErrorKind :: Other ) ,
627+ ] ;
628+ let mut spi = Mock :: new ( & expectations) ;
629+
630+ assert_eq ! ( SpiBus :: write( & mut spi, & [ 1 , 2 ] ) , Err ( spi:: ErrorKind :: Other ) ) ;
631+ assert_eq ! ( SpiBus :: write( & mut spi, & [ 0x09 ] ) , Err ( spi:: ErrorKind :: Other ) ) ;
632+ assert_eq ! (
633+ FullDuplex :: read( & mut spi) ,
634+ Err ( nb:: Error :: Other ( spi:: ErrorKind :: Other ) )
635+ ) ;
636+ assert_eq ! ( SpiBus :: write( & mut spi, & [ 0xfe ] ) , Err ( spi:: ErrorKind :: Other ) ) ;
637+ assert_eq ! (
638+ FullDuplex :: read( & mut spi) ,
639+ Err ( nb:: Error :: Other ( spi:: ErrorKind :: Other ) )
640+ ) ;
641+ let mut v = vec ! [ 3 , 4 ] ;
642+ assert_eq ! (
643+ SpiBus :: transfer_in_place( & mut spi, & mut v) ,
644+ Err ( spi:: ErrorKind :: Other )
645+ ) ;
646+
647+ spi. done ( ) ;
648+ }
649+
650+ #[ test]
651+ fn test_spi_mock_device_error ( ) {
652+ use eh1:: spi:: SpiDevice ;
653+
654+ let expectations = [
655+ Transaction :: transaction_start ( ) . with_error ( spi:: ErrorKind :: Other ) ,
656+ Transaction :: transaction_start ( ) ,
657+ Transaction :: transfer_in_place ( vec ! [ 3 , 4 ] , vec ! [ 5 , 6 ] ) ,
658+ Transaction :: transaction_end ( ) . with_error ( spi:: ErrorKind :: Other ) ,
659+ ] ;
660+ let mut spi = Mock :: new ( & expectations) ;
661+
662+ let mut v = vec ! [ 3 , 4 ] ;
663+
664+ // exits early due to returned error on transaction start
665+ assert_eq ! (
666+ SpiDevice :: transfer_in_place( & mut spi, & mut v) ,
667+ Err ( spi:: ErrorKind :: Other )
668+ ) ;
669+ // transfers successfully, but transaction_end() results in error
670+ assert_eq ! (
671+ SpiDevice :: transfer_in_place( & mut spi, & mut v) ,
672+ Err ( spi:: ErrorKind :: Other )
673+ ) ;
674+ assert_eq ! ( v, vec![ 5 , 6 ] ) ;
675+
676+ spi. done ( ) ;
677+ }
678+
541679 #[ test]
542680 fn test_spi_mock_multiple1 ( ) {
543681 use eh1:: spi:: SpiBus ;
0 commit comments