From 1a45e07b90e3804bcc6ba4e46a154cb2e6ce3086 Mon Sep 17 00:00:00 2001 From: Callum Dunster Date: Thu, 14 Sep 2023 15:55:16 +0200 Subject: [PATCH] Add support for ToggleableOutputPin for pin::Mock --- src/eh0/pin.rs | 54 ++++++++++++++++++++++++++++++++++++++++++++++---- src/eh1/pin.rs | 53 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 98 insertions(+), 9 deletions(-) diff --git a/src/eh0/pin.rs b/src/eh0/pin.rs index 77607cf..207ff44 100644 --- a/src/eh0/pin.rs +++ b/src/eh0/pin.rs @@ -1,7 +1,8 @@ -//! Mock digital [`InputPin`] and [`OutputPin`] v2 implementations +//! Mock digital [`InputPin`], [`OutputPin`], and [`ToggleableOutputPin`] v2 implementations //! //! [`InputPin`]: https://docs.rs/embedded-hal/0.2/embedded_hal/digital/v2/trait.InputPin.html //! [`OutputPin`]: https://docs.rs/embedded-hal/0.2/embedded_hal/digital/v2/trait.OutputPin.html +//! [`ToggleableOutputPin`]: https://docs.rs/embedded-hal/0.2/embedded_hal/digital/v2/trait.ToggleableOutputPin.html //! //! ``` //! # use eh0 as embedded_hal; @@ -9,7 +10,7 @@ //! //! use embedded_hal_mock::eh0::MockError; //! use embedded_hal_mock::eh0::pin::{Transaction as PinTransaction, Mock as PinMock, State as PinState}; -//! use embedded_hal::digital::v2::{InputPin, OutputPin}; +//! use embedded_hal::digital::v2::{InputPin, OutputPin, ToggleableOutputPin}; //! //! let err = MockError::Io(ErrorKind::NotConnected); //! @@ -19,6 +20,7 @@ //! PinTransaction::get(PinState::High), //! PinTransaction::set(PinState::Low), //! PinTransaction::set(PinState::High).with_error(err.clone()), +//! PinTransaction::toggle(), //! ]; //! //! // Create pin @@ -31,6 +33,8 @@ //! pin.set_low().unwrap(); //! pin.set_high().expect_err("expected error return"); //! +//! pin.toggle().unwrap(); +//! //! pin.done(); //! //! // Update expectations @@ -44,7 +48,7 @@ use super::error::MockError; use crate::common::Generic; use eh0 as embedded_hal; -use embedded_hal::digital::v2::{InputPin, OutputPin}; +use embedded_hal::digital::v2::{InputPin, OutputPin, ToggleableOutputPin}; use embedded_hal::PwmPin; /// The type used for the duty of the [`PwmPin`] mock. @@ -81,6 +85,11 @@ impl Transaction { Transaction::new(TransactionKind::Get(state)) } + /// Create a new toggle transaction + pub fn toggle() -> Transaction { + Transaction::new(TransactionKind::Toggle) + } + /// Create a new get transaction pub fn set(state: State) -> Transaction { Transaction::new(TransactionKind::Set(state)) @@ -134,6 +143,8 @@ pub enum TransactionKind { Set(State), /// Get the pin state Get(State), + /// Toggle for an expected toggle of the pin + Toggle, /// Disable a [`PwmPin`] using [`PwmPin::disable`] Disable, /// Enable a [`PwmPin`] using [`PwmPin::enable`] @@ -157,7 +168,7 @@ impl TransactionKind { /// Specifies whether the actual API returns a [`Result`] (= supports errors) or not. fn supports_errors(&self) -> bool { match self { - TransactionKind::Set(_) | TransactionKind::Get(_) => true, + TransactionKind::Set(_) | TransactionKind::Get(_) | TransactionKind::Toggle => true, _ => false, } } @@ -243,6 +254,24 @@ impl InputPin for Mock { } } +/// Single digital output pin that can be toggled between high and low states +impl ToggleableOutputPin for Mock { + /// Error type + type Error = MockError; + + /// Toggle the pin low to high or high to low + fn toggle(&mut self) -> Result<(), Self::Error> { + let Transaction { kind, err } = self.next().expect("no expectation for pin::toggle call"); + + assert_eq!(kind, TransactionKind::Toggle, "expected pin::toggle"); + + match err { + Some(e) => Err(e), + None => Ok(()), + } + } +} + impl PwmPin for Mock { type Duty = PwmDuty; @@ -348,6 +377,23 @@ mod test { pin.done(); } + #[test] + fn test_toggleable_output_pin() { + let expectations = [ + Transaction::new(Toggle), + Transaction::toggle(), + Transaction::new(Toggle).with_error(MockError::Io(ErrorKind::NotConnected)), + ]; + let mut pin = Mock::new(&expectations); + + pin.toggle().unwrap(); + pin.toggle().unwrap(); + + pin.toggle().expect_err("expected error return"); + + pin.done(); + } + #[test] fn test_pwm_pin() { let expected_duty = 10_000; diff --git a/src/eh1/pin.rs b/src/eh1/pin.rs index ef2c1fa..fb71b55 100644 --- a/src/eh1/pin.rs +++ b/src/eh1/pin.rs @@ -1,7 +1,8 @@ -//! Mock digital [`InputPin`] and [`OutputPin`] implementations +//! Mock digital [`InputPin`], [`OutputPin`], and [`ToggleableOutputPin`] implementations //! //! [`InputPin`]: https://docs.rs/embedded-hal/1.0.0-rc.2/embedded_hal/digital/trait.InputPin.html //! [`OutputPin`]: https://docs.rs/embedded-hal/1.0.0-rc.2/embedded_hal/digital/trait.OutputPin.html +//! [`ToggleableOutputPin`]: https://docs.rs/embedded-hal/1.0.0-rc.2/embedded_hal/digital/trait.ToggleableOutputPin.html //! //! ``` //! # use eh1 as embedded_hal; @@ -9,7 +10,7 @@ //! //! use embedded_hal_mock::eh1::MockError; //! use embedded_hal_mock::eh1::pin::{Transaction as PinTransaction, Mock as PinMock, State as PinState}; -//! use embedded_hal::digital::{InputPin, OutputPin}; +//! use embedded_hal::digital::{InputPin, OutputPin, ToggleableOutputPin}; //! //! let err = MockError::Io(ErrorKind::NotConnected); //! @@ -19,6 +20,7 @@ //! PinTransaction::get(PinState::High), //! PinTransaction::set(PinState::Low), //! PinTransaction::set(PinState::High).with_error(err.clone()), +//! PinTransaction::toggle(), //! ]; //! //! // Create pin @@ -31,6 +33,8 @@ //! pin.set_low().unwrap(); //! pin.set_high().expect_err("expected error return"); //! +//! pin.toggle().unwrap(); +//! //! pin.done(); //! //! // Update expectations @@ -44,7 +48,7 @@ use crate::common::Generic; use crate::eh1::error::MockError; use eh1 as embedded_hal; -use embedded_hal::digital::{ErrorType, InputPin, OutputPin}; +use embedded_hal::digital::{ErrorType, InputPin, OutputPin, ToggleableOutputPin}; /// MockPin transaction #[derive(PartialEq, Eq, Clone, Debug)] @@ -82,6 +86,11 @@ impl Transaction { Transaction::new(TransactionKind::Set(state)) } + /// Create a new toggle transaction + pub fn toggle() -> Transaction { + Transaction::new(TransactionKind::Toggle) + } + /// Add an error return to a transaction /// /// This is used to mock failure behaviours. @@ -105,6 +114,8 @@ pub enum TransactionKind { Set(State), /// Get the pin state Get(State), + /// Toggle for an expected toggle of the pin + Toggle, } impl TransactionKind { @@ -199,16 +210,31 @@ impl InputPin for Mock { } } +/// Single digital output pin that can be toggled between high and low states +impl ToggleableOutputPin for Mock { + /// Toggle the pin low to high or high to low + fn toggle(&mut self) -> Result<(), Self::Error> { + let Transaction { kind, err } = self.next().expect("no expectation for pin::toggle call"); + + assert_eq!(kind, TransactionKind::Toggle, "expected pin::toggle"); + + match err { + Some(e) => Err(e), + None => Ok(()), + } + } +} + #[cfg(test)] mod test { use super::super::error::MockError; - use super::TransactionKind::{Get, Set}; + use super::TransactionKind::{Get, Set, Toggle}; use super::*; use std::io::ErrorKind; use eh1 as embedded_hal; - use embedded_hal::digital::{InputPin, OutputPin}; + use embedded_hal::digital::{InputPin, OutputPin, ToggleableOutputPin}; #[test] fn test_input_pin() { @@ -247,4 +273,21 @@ mod test { pin.done(); } + + #[test] + fn test_toggleable_output_pin() { + let expectations = [ + Transaction::new(Toggle), + Transaction::toggle(), + Transaction::new(Toggle).with_error(MockError::Io(ErrorKind::NotConnected)), + ]; + let mut pin = Mock::new(&expectations); + + pin.toggle().unwrap(); + pin.toggle().unwrap(); + + pin.toggle().expect_err("expected error return"); + + pin.done(); + } }