switch_hal/
mock.rs

1//! Mock implementations of [InputPin](embedded_hal::digital::v2::InputPin) and [OutputPin](embedded_hal::digital::v2::OutputPin).
2//!
3//! WARNING: May be removed if `embedded_hal_mock` crate is improved.
4//! https://github.com/dbrgn/embedded-hal-mock/issues/30
5//!
6//! This is part of the main crate so it is accessible to doctests.
7//! Otherwise, I would have created a tests/mock/mod.rs file.
8use embedded_hal::digital::v2::toggleable;
9use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
10
11#[derive(PartialEq, Eq, Debug)]
12pub enum State {
13    Low,
14    High,
15}
16
17pub struct Pin {
18    state: Option<State>,
19}
20
21impl Pin {
22    pub fn new() -> Self {
23        Pin { state: None }
24    }
25
26    pub fn with_state(state: State) -> Self {
27        Pin { state: Some(state) }
28    }
29}
30
31type MockError = &'static str;
32
33impl InputPin for Pin {
34    type Error = MockError;
35
36    fn is_high(&self) -> Result<bool, Self::Error> {
37        match self.state {
38            Some(State::High) => Ok(true),
39            Some(State::Low) => Ok(false),
40            None => Err("state not set"),
41        }
42    }
43
44    fn is_low(&self) -> Result<bool, Self::Error> {
45        match self.is_high() {
46            Ok(v) => Ok(!v),
47            Err(e) => Err(e),
48        }
49    }
50}
51
52impl OutputPin for Pin {
53    type Error = MockError;
54
55    fn set_low(&mut self) -> Result<(), Self::Error> {
56        self.state = Some(State::Low);
57        Ok(())
58    }
59
60    fn set_high(&mut self) -> Result<(), Self::Error> {
61        self.state = Some(State::High);
62        Ok(())
63    }
64}
65
66impl StatefulOutputPin for Pin {
67    fn is_set_low(&self) -> Result<bool, Self::Error> {
68        self.is_low()
69    }
70
71    fn is_set_high(&self) -> Result<bool, Self::Error> {
72        self.is_high()
73    }
74}
75
76impl toggleable::Default for Pin {}
77
78#[cfg(test)]
79mod test {
80    use super::*;
81
82    mod new {
83        use super::*;
84
85        #[test]
86        fn state_is_unitialized() {
87            let pin = Pin::new();
88            assert_eq!(None, pin.state);
89            pin.is_low().expect_err("Expected unitialized pin");
90        }
91    }
92
93    mod input_pin {
94        use super::*;
95
96        #[test]
97        fn error_when_uninitialized() {
98            let pin = Pin { state: None };
99            pin.is_high().expect_err("Expected unitialized pin");
100        }
101
102        mod is_high {
103            use super::*;
104
105            #[test]
106            fn returns_true_when_state_is_high() {
107                let pin = Pin::with_state(State::High);
108                assert_eq!(true, pin.is_high().unwrap());
109            }
110
111            #[test]
112            fn returns_false_when_state_is_low() {
113                let pin = Pin::with_state(State::Low);
114                assert_eq!(false, pin.is_high().unwrap());
115            }
116        }
117
118        mod is_low {
119            use super::*;
120
121            #[test]
122            fn returns_false_when_state_is_high() {
123                let pin = Pin::with_state(State::High);
124                assert_eq!(false, pin.is_low().unwrap());
125            }
126
127            #[test]
128            fn returns_true_when_state_is_high() {
129                let pin = Pin::with_state(State::Low);
130                assert_eq!(true, pin.is_low().unwrap());
131            }
132        }
133    }
134
135    mod output_pin {
136        use super::*;
137
138        #[test]
139        fn set_low() {
140            let mut pin = Pin::new();
141            pin.set_low().unwrap();
142
143            assert_eq!(true, pin.is_low().unwrap());
144        }
145
146        #[test]
147        fn set_high() {
148            let mut pin = Pin::new();
149            pin.set_high().unwrap();
150
151            assert_eq!(true, pin.is_high().unwrap());
152        }
153    }
154
155    mod statful_output_pin {
156        use super::*;
157
158        #[test]
159        fn error_when_uninitialized() {
160            let pin = Pin { state: None };
161            pin.is_set_high().expect_err("Expected unitialized pin");
162        }
163
164        mod is_set_low {
165            use super::*;
166
167            #[test]
168            fn returns_false_when_state_is_high() {
169                let pin = Pin::with_state(State::High);
170                assert_eq!(false, pin.is_set_low().unwrap());
171            }
172
173            #[test]
174            fn returns_true_when_state_is_high() {
175                let pin = Pin::with_state(State::Low);
176                assert_eq!(true, pin.is_set_low().unwrap());
177            }
178        }
179
180        mod is_set_high {
181            use super::*;
182
183            #[test]
184            fn returns_true_when_state_is_high() {
185                let pin = Pin::with_state(State::High);
186                assert_eq!(true, pin.is_set_high().unwrap());
187            }
188
189            #[test]
190            fn returns_false_when_state_is_low() {
191                let pin = Pin::with_state(State::Low);
192                assert_eq!(false, pin.is_set_high().unwrap());
193            }
194        }
195
196        mod toggleable {
197            use super::*;
198            use embedded_hal::digital::v2::ToggleableOutputPin;
199
200            #[test]
201            fn default_toggleable_impl() {
202                let mut pin = Pin::with_state(State::Low);
203                pin.toggle().unwrap();
204                assert_eq!(true, pin.is_set_high().unwrap());
205            }
206        }
207    }
208}