use embedded_hal_mock::eh1::spi::{Mock as SpiMock, Transaction as SpiTrans}; use mcp4x::{ic, interface, Channel, Error, Mcp4x}; macro_rules! device_support { ($create:ident, $destroy:ident, $ic:ident) => { pub fn $create( transactions: &[SpiTrans], ) -> Mcp4x>, ic::$ic> { let wrapped: Vec> = transactions .iter() .flat_map(|trans| { [ SpiTrans::transaction_start(), trans.clone(), SpiTrans::transaction_end(), ] }) .collect(); Mcp4x::$create(SpiMock::new(&wrapped)) } pub fn $destroy(dev: Mcp4x>, ic::$ic>) { dev.$destroy().done(); } }; } device_support!(new_mcp41x, destroy_mcp41x, Mcp41x); device_support!(new_mcp42x, destroy_mcp42x, Mcp42x); #[macro_export] macro_rules! test { ($name:ident, $method:ident, $create:ident, $destroy:ident, $cmd:expr, $expected_value:expr, $( $arg:expr ),* ) => { #[test] fn $name() { let trans = [SpiTrans::write_vec(vec![$cmd, $expected_value])]; let mut dev = $create(&trans); dev.$method($($arg),*).unwrap(); $destroy(dev); } }; } mod mcp41x { use super::*; test!( set_position_ch0, set_position, new_mcp41x, destroy_mcp41x, 0b0001_0001, 50, Channel::Ch0, 50 ); test!( set_position_all, set_position, new_mcp41x, destroy_mcp41x, 0b0001_0011, 50, Channel::All, 50 ); test!( shutdown_ch0, shutdown, new_mcp41x, destroy_mcp41x, 0b0010_0001, 0, Channel::Ch0 ); test!( shutdown_all, shutdown, new_mcp41x, destroy_mcp41x, 0b0010_0011, 0, Channel::All ); fn assert_wrong_channel(result: &Result>) { match result { Err(Error::WrongChannel) => (), _ => panic!("Wrong channel not reported."), } } #[test] fn wrong_channel_matches() { assert_wrong_channel::<(), ()>(&Err(Error::WrongChannel)); } #[should_panic] #[test] fn wrong_channel_can_fail() { assert_wrong_channel::<(), ()>(&Ok(())); } #[test] fn shutdown_cannot_provide_invalid_channel_ch1() { let mut dev = new_mcp41x(&[]); assert_wrong_channel(&dev.shutdown(Channel::Ch1)); dev.destroy_mcp41x().done(); } #[test] fn set_position_cannot_provide_invalid_channel() { let mut dev = new_mcp41x(&[]); assert_wrong_channel(&dev.set_position(Channel::Ch1, 0)); dev.destroy_mcp41x().done(); } } mod mcp42x { use super::*; test!( set_position_ch0, set_position, new_mcp42x, destroy_mcp42x, 0b0001_0001, 50, Channel::Ch0, 50 ); test!( set_position_ch1, set_position, new_mcp42x, destroy_mcp42x, 0b0001_0010, 50, Channel::Ch1, 50 ); test!( set_position_all, set_position, new_mcp42x, destroy_mcp42x, 0b0001_0011, 50, Channel::All, 50 ); test!( shutdown_ch0, shutdown, new_mcp42x, destroy_mcp42x, 0b0010_0001, 0, Channel::Ch0 ); test!( shutdown_ch1, shutdown, new_mcp42x, destroy_mcp42x, 0b0010_0010, 0, Channel::Ch1 ); test!( shutdown_all, shutdown, new_mcp42x, destroy_mcp42x, 0b0010_0011, 0, Channel::All ); }