Skip to content

Commit

Permalink
add SetDutyCycle mock
Browse files Browse the repository at this point in the history
this is the 1.0 equivalent of the old `PwmPin` trait (the mock for this
has been added in dbrgn#52).

note that the test coverage is fully handled by the doc test which is
why there's no additional `mod test` in this file.

this fixes dbrgn#73
  • Loading branch information
rursprung committed Nov 5, 2023
1 parent 3abcea6 commit 69d3d82
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 3 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
## Unreleased

### Added
- Implement mock for `embedded_hal::pwm::SetDutyCycle`

### Fixed

Expand Down
1 change: 1 addition & 0 deletions src/eh1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ pub use crate::eh1::error::MockError;
pub mod delay;
pub mod i2c;
pub mod pin;
pub mod pwm;
pub mod serial;
pub mod spi;
6 changes: 3 additions & 3 deletions src/eh1/pin.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Mock digital [`InputPin`] and [`OutputPin`] v2 implementations
//! Mock digital [`InputPin`] and [`OutputPin`] implementations
//!
//! [`InputPin`]: https://docs.rs/embedded-hal/1.0.0-alpha.6/embedded_hal/digital/trait.InputPin.html
//! [`OutputPin`]: https://docs.rs/embedded-hal/1.0.0-alpha.6/embedded_hal/digital/trait.OutputPin.html
//! [`InputPin`]: https://docs.rs/embedded-hal/1.0.0-rc.1/embedded_hal/digital/trait.InputPin.html
//! [`OutputPin`]: https://docs.rs/embedded-hal/1.0.0-rc.1/embedded_hal/digital/trait.OutputPin.html
//!
//! ```
//! # use eh1 as embedded_hal;
Expand Down
127 changes: 127 additions & 0 deletions src/eh1/pwm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
//! Mock implementations for
//! [`embedded_hal::pwm`](https://docs.rs/embedded-hal/1.0.0-rc.1/embedded_hal/pwm/index.html).
//!
//! Usage example:
//! ```
//! use std::io::ErrorKind;
//!
//! # use eh1 as embedded_hal;
//! use embedded_hal::pwm::SetDutyCycle;
//! use embedded_hal_mock::eh1::{
//! pwm::{Mock as PwmMock, Transaction as PwmTransaction},
//! MockError,
//! };
//!
//! // Configure expectations
//! let expectations = [
//! PwmTransaction::get_max_duty_cycle(100),
//! PwmTransaction::set_duty_cycle(50),
//! PwmTransaction::set_duty_cycle(101).with_error(MockError::Io(ErrorKind::NotConnected)),
//! ];
//!
//! // Create pin
//! let mut pwm = PwmMock::new(&expectations);
//!
//! // Run and test
//! pwm.set_duty_cycle_percent(50).unwrap();
//! pwm.set_duty_cycle(101).expect_err("expected error return");
//!
//! // Finalise expectations
//! pwm.done();
//! ```

use eh1::pwm::{ErrorKind, ErrorType, SetDutyCycle};

use crate::{common::Generic, eh1::MockError};

/// MockPwm transaction
#[derive(PartialEq, Clone, Debug)]
pub struct Transaction {
/// Kind is the transaction kind (and data) expected
kind: TransactionKind,
/// Err is an optional error return for a transaction.
/// This is in addition to kind to allow validation that the transaction kind
/// is correct prior to returning the error.
err: Option<MockError>,
}

impl Transaction {
/// Create a new PWM transaction
pub fn new(kind: TransactionKind) -> Transaction {
Transaction { kind, err: None }
}

/// Create a new [`TransactionKind::GetMaxDutyCycle`] transaction for [`SetDutyCycle::get_max_duty_cycle`].
pub fn get_max_duty_cycle(duty: u16) -> Transaction {
Transaction::new(TransactionKind::GetMaxDutyCycle(duty))
}

/// Create a new [`TransactionKind::SetDutyCycle`] transaction for [`SetDutyCycle::set_duty_cycle`].
pub fn set_duty_cycle(duty: u16) -> Transaction {
Transaction::new(TransactionKind::SetDutyCycle(duty))
}

/// Add an error return to a transaction
///
/// This is used to mock failure behaviours.
pub fn with_error(mut self, error: MockError) -> Self {
self.err = Some(error);
self
}
}

/// MockPwm transaction kind
#[derive(PartialEq, Clone, Debug)]
pub enum TransactionKind {
/// [`SetDutyCycle::get_max_duty_cycle`] which will return the defined duty.
GetMaxDutyCycle(u16),
/// [`SetDutyCycle::set_duty_cycle`] with the expected duty.
SetDutyCycle(u16),
}

/// Mock PWM `SetDutyCycle` implementation
pub type Mock = Generic<Transaction>;

impl eh1::pwm::Error for MockError {
fn kind(&self) -> ErrorKind {
ErrorKind::Other
}
}

impl ErrorType for Mock {
type Error = MockError;
}

impl SetDutyCycle for Mock {
fn get_max_duty_cycle(&self) -> u16 {
let mut s = self.clone();

let Transaction { kind, err } = s
.next()
.expect("no expectation for get_max_duty_cycle call");

assert_eq!(err, None, "error not supported by get_max_duty_cycle!");

match kind {
TransactionKind::GetMaxDutyCycle(duty) => duty,
other => panic!("expected get_max_duty_cycle, got {:?}", other),
}
}

fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> {
let Transaction { kind, err } =
self.next().expect("no expectation for set_duty_cycle call");

assert_eq!(
kind,
TransactionKind::SetDutyCycle(duty),
"expected set_duty_cycle"
);

if let Some(e) = err {
Err(e)
} else {
Ok(())
}
}
}

0 comments on commit 69d3d82

Please sign in to comment.