From e5f6bb7f158ac63b987f645dfbb4150af35d4f30 Mon Sep 17 00:00:00 2001 From: Kevin Thomas Date: Wed, 25 Mar 2026 11:25:04 -0400 Subject: [PATCH] feat: add unit tests for blink driver with mock pin --- drivers/0x02_blink_rust/Cargo.toml | 8 ++ drivers/0x02_blink_rust/src/blink.rs | 118 +++++++++++++++++++++++++-- drivers/0x02_blink_rust/src/lib.rs | 8 ++ drivers/0x02_blink_rust/src/main.rs | 2 +- 4 files changed, 126 insertions(+), 10 deletions(-) create mode 100644 drivers/0x02_blink_rust/src/lib.rs diff --git a/drivers/0x02_blink_rust/Cargo.toml b/drivers/0x02_blink_rust/Cargo.toml index 2a17bfe..dde36b5 100644 --- a/drivers/0x02_blink_rust/Cargo.toml +++ b/drivers/0x02_blink_rust/Cargo.toml @@ -5,6 +5,14 @@ name = "blink" version = "0.1.0" license = "MIT or Apache-2.0" +[lib] +name = "blink_lib" +path = "src/lib.rs" + +[[bin]] +name = "blink" +path = "src/main.rs" + [build-dependencies] regex = "1.11.0" diff --git a/drivers/0x02_blink_rust/src/blink.rs b/drivers/0x02_blink_rust/src/blink.rs index 7cba0b4..46fb660 100644 --- a/drivers/0x02_blink_rust/src/blink.rs +++ b/drivers/0x02_blink_rust/src/blink.rs @@ -26,29 +26,25 @@ //! SOFTWARE. use embedded_hal::digital::{OutputPin, StatefulOutputPin}; -use rp235x_hal as hal; -use hal::gpio::{FunctionNull, FunctionSio, FunctionSioOutput, Pin, PullDown, SioOutput, ValidFunction}; /// GPIO output / LED blink driver that owns a single output pin. -pub struct BlinkDriver { - pin: Pin, +pub struct BlinkDriver { + pin: P, } -impl>> BlinkDriver { +impl BlinkDriver

{ /// Initialize a GPIO pin as a push-pull digital output. /// - /// Calls into_push_pull_output() to configure the pin for output. /// The initial drive level is low (LED off). /// /// # Arguments /// - /// * `pin` - GPIO pin number to configure as a digital output. + /// * `pin` - GPIO pin configured as a digital output. /// /// # Returns /// /// A new BlinkDriver instance owning the configured pin. - pub fn init(pin: Pin) -> Self { - let mut pin = pin.into_push_pull_output(); + pub fn init(mut pin: P) -> Self { pin.set_low().unwrap(); Self { pin } } @@ -97,4 +93,108 @@ impl>> BlinkDriver } } +#[cfg(test)] +mod tests { + use super::*; + use core::convert::Infallible; + use embedded_hal::digital::ErrorType; + + struct MockPin { + state: bool, + } + + impl MockPin { + fn new() -> Self { + Self { state: false } + } + } + + impl ErrorType for MockPin { + type Error = Infallible; + } + + impl OutputPin for MockPin { + fn set_low(&mut self) -> Result<(), Self::Error> { + self.state = false; + Ok(()) + } + fn set_high(&mut self) -> Result<(), Self::Error> { + self.state = true; + Ok(()) + } + } + + impl StatefulOutputPin for MockPin { + fn is_set_high(&mut self) -> Result { + Ok(self.state) + } + fn is_set_low(&mut self) -> Result { + Ok(!self.state) + } + fn toggle(&mut self) -> Result<(), Self::Error> { + self.state = !self.state; + Ok(()) + } + } + + #[test] + fn init_starts_low() { + let drv = BlinkDriver::init(MockPin::new()); + assert!(!drv.pin.state); + } + + #[test] + fn on_sets_high() { + let mut drv = BlinkDriver::init(MockPin::new()); + drv.on(); + assert!(drv.pin.state); + } + + #[test] + fn off_sets_low() { + let mut drv = BlinkDriver::init(MockPin::new()); + drv.on(); + drv.off(); + assert!(!drv.pin.state); + } + + #[test] + fn toggle_from_low_goes_high() { + let mut drv = BlinkDriver::init(MockPin::new()); + drv.toggle(); + assert!(drv.pin.state); + } + + #[test] + fn toggle_from_high_goes_low() { + let mut drv = BlinkDriver::init(MockPin::new()); + drv.on(); + drv.toggle(); + assert!(!drv.pin.state); + } + + #[test] + fn get_state_reflects_on() { + let mut drv = BlinkDriver::init(MockPin::new()); + drv.on(); + assert!(drv.get_state()); + } + + #[test] + fn get_state_reflects_off() { + let mut drv = BlinkDriver::init(MockPin::new()); + drv.on(); + drv.off(); + assert!(!drv.get_state()); + } + + #[test] + fn double_toggle_returns_to_original() { + let mut drv = BlinkDriver::init(MockPin::new()); + drv.toggle(); + drv.toggle(); + assert!(!drv.get_state()); + } +} + // End of file diff --git a/drivers/0x02_blink_rust/src/lib.rs b/drivers/0x02_blink_rust/src/lib.rs new file mode 100644 index 0000000..4f3672c --- /dev/null +++ b/drivers/0x02_blink_rust/src/lib.rs @@ -0,0 +1,8 @@ +//! @file lib.rs +//! @brief Library root for the blink driver crate +//! @author Kevin Thomas +//! @date 2025 + +#![no_std] + +pub mod blink; diff --git a/drivers/0x02_blink_rust/src/main.rs b/drivers/0x02_blink_rust/src/main.rs index 2ed9da4..d3ecfe5 100644 --- a/drivers/0x02_blink_rust/src/main.rs +++ b/drivers/0x02_blink_rust/src/main.rs @@ -207,7 +207,7 @@ fn main() -> ! { let pins = init_pins(pac.IO_BANK0, pac.PADS_BANK0, pac.SIO, &mut pac.RESETS); let uart = init_uart(pac.UART0, pins.gpio0, pins.gpio1, &mut pac.RESETS, &clocks); let mut delay = init_delay(&clocks); - let mut led = blink::BlinkDriver::init(pins.gpio25); + let mut led = blink::BlinkDriver::init(pins.gpio25.into_push_pull_output()); uart.write_full_blocking(b"Blink driver initialized on GPIO 25\r\n"); loop { led.toggle();