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}
@@ -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