|
| 1 | +//! Mock implementations for [`embedded_hal::pwm`]. |
| 2 | +//! |
| 3 | +//! Usage example: |
| 4 | +//! ``` |
| 5 | +//! use std::io::ErrorKind; |
| 6 | +//! |
| 7 | +//! use embedded_hal_mock::MockError; |
| 8 | +//! use embedded_hal_mock::pwm::{Transaction as PwmTransaction, Mock as PwmMock}; |
| 9 | +//! use embedded_hal::pwm::SetDutyCycle; |
| 10 | +//! |
| 11 | +//! let err = MockError::Io(ErrorKind::NotConnected); |
| 12 | +//! |
| 13 | +//! // Configure expectations |
| 14 | +//! let expectations = [ |
| 15 | +//! PwmTransaction::get_max_duty_cycle(100), |
| 16 | +//! PwmTransaction::set_duty_cycle(50), |
| 17 | +//! PwmTransaction::set_duty_cycle(101).with_error(err.clone()), |
| 18 | +//! ]; |
| 19 | +//! |
| 20 | +//! // Create pin |
| 21 | +//! let mut pwm = PwmMock::new(&expectations); |
| 22 | +//! |
| 23 | +//! // Run and test |
| 24 | +//! pwm.set_duty_cycle_percent(50).unwrap(); |
| 25 | +//! pwm.set_duty_cycle(101).expect_err("expected error return"); |
| 26 | +//! |
| 27 | +//! pwm.done(); |
| 28 | +//! |
| 29 | +//! // Update expectations |
| 30 | +//! pwm.expect(&[]); |
| 31 | +//! // ... |
| 32 | +//! pwm.done(); |
| 33 | +//! ``` |
| 34 | +
|
| 35 | +use crate::common::Generic; |
| 36 | +use crate::error::MockError; |
| 37 | +use embedded_hal::pwm::{ErrorKind, ErrorType, SetDutyCycle}; |
| 38 | + |
| 39 | +/// MockPwm transaction |
| 40 | +#[derive(PartialEq, Clone, Debug)] |
| 41 | +pub struct Transaction { |
| 42 | + /// Kind is the transaction kind (and data) expected |
| 43 | + kind: TransactionKind, |
| 44 | + /// Err is an optional error return for a transaction. |
| 45 | + /// This is in addition to kind to allow validation that the transaction kind |
| 46 | + /// is correct prior to returning the error. |
| 47 | + err: Option<MockError>, |
| 48 | +} |
| 49 | + |
| 50 | +impl Transaction { |
| 51 | + /// Create a new PWM transaction |
| 52 | + pub fn new(kind: TransactionKind) -> Transaction { |
| 53 | + Transaction { kind, err: None } |
| 54 | + } |
| 55 | + |
| 56 | + /// Create a new [`TransactionKind::GetMaxDutyCycle`] transaction for [`SetDutyCycle::get_max_duty_cycle`]. |
| 57 | + pub fn get_max_duty_cycle(duty: u16) -> Transaction { |
| 58 | + Transaction::new(TransactionKind::GetMaxDutyCycle(duty)) |
| 59 | + } |
| 60 | + |
| 61 | + /// Create a new [`TransactionKind::SetDutyCycle`] transaction for [`SetDutyCycle::set_duty_cycle`]. |
| 62 | + pub fn set_duty_cycle(duty: u16) -> Transaction { |
| 63 | + Transaction::new(TransactionKind::SetDutyCycle(duty)) |
| 64 | + } |
| 65 | + |
| 66 | + /// Add an error return to a transaction |
| 67 | + /// |
| 68 | + /// This is used to mock failure behaviours. |
| 69 | + pub fn with_error(mut self, error: MockError) -> Self { |
| 70 | + self.err = Some(error); |
| 71 | + self |
| 72 | + } |
| 73 | +} |
| 74 | + |
| 75 | +/// MockPwm transaction kind |
| 76 | +#[derive(PartialEq, Clone, Debug)] |
| 77 | +pub enum TransactionKind { |
| 78 | + /// [`SetDutyCycle::get_max_duty_cycle`] which will return the defined duty. |
| 79 | + GetMaxDutyCycle(u16), |
| 80 | + /// [`SetDutyCycle::set_duty_cycle`] with the expected duty. |
| 81 | + SetDutyCycle(u16), |
| 82 | +} |
| 83 | + |
| 84 | +/// Mock SetDutyCycle implementation |
| 85 | +pub type Mock = Generic<Transaction>; |
| 86 | + |
| 87 | +impl embedded_hal::pwm::Error for MockError { |
| 88 | + fn kind(&self) -> ErrorKind { |
| 89 | + ErrorKind::Other |
| 90 | + } |
| 91 | +} |
| 92 | + |
| 93 | +impl ErrorType for Mock { |
| 94 | + type Error = MockError; |
| 95 | +} |
| 96 | + |
| 97 | +impl SetDutyCycle for Mock { |
| 98 | + fn get_max_duty_cycle(&self) -> u16 { |
| 99 | + let mut s = self.clone(); |
| 100 | + |
| 101 | + let Transaction { kind, err } = s |
| 102 | + .next() |
| 103 | + .expect("no expectation for get_max_duty_cycle call"); |
| 104 | + |
| 105 | + assert_eq!(err, None, "error not supported by get_max_duty_cycle!"); |
| 106 | + |
| 107 | + if let TransactionKind::GetMaxDutyCycle(duty) = kind { |
| 108 | + duty |
| 109 | + } else { |
| 110 | + unreachable!(); |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> { |
| 115 | + let Transaction { kind, err } = |
| 116 | + self.next().expect("no expectation for set_duty_cycle call"); |
| 117 | + |
| 118 | + assert_eq!( |
| 119 | + kind, |
| 120 | + TransactionKind::SetDutyCycle(duty), |
| 121 | + "expected set_duty_cycle" |
| 122 | + ); |
| 123 | + |
| 124 | + if let Some(e) = err { |
| 125 | + Err(e) |
| 126 | + } else { |
| 127 | + Ok(()) |
| 128 | + } |
| 129 | + } |
| 130 | +} |
0 commit comments