use urm37::protocol::{Frame, Command, EepromRegister};
use urm37::error::Error;
use std::cell::RefCell;
use embedded_io::{ErrorType, Read, ReadExactError};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MockError {
Eof,
}
impl std::fmt::Display for MockError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MockError::Eof => write!(f, "end of file"),
}
}
}
impl std::error::Error for MockError {}
impl embedded_io::Error for MockError {
fn kind(&self) -> embedded_io::ErrorKind {
match self {
MockError::Eof => embedded_io::ErrorKind::Other,
}
}
}
pub struct MockUart {
read_buffer: RefCell<std::vec::Vec<u8>>,
write_buffer: RefCell<std::vec::Vec<u8>>,
}
impl MockUart {
pub fn new(responses: std::vec::Vec<u8>) -> Self {
Self {
read_buffer: RefCell::new(responses),
write_buffer: RefCell::new(std::vec::Vec::new()),
}
}
pub fn written_data(&self) -> std::vec::Vec<u8> {
self.write_buffer.borrow().clone()
}
}
impl ErrorType for MockUart {
type Error = MockError;
}
impl embedded_io::Read for MockUart {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
let mut buffer = self.read_buffer.borrow_mut();
if buffer.is_empty() {
return Err(MockError::Eof);
}
let len = std::cmp::min(buf.len(), buffer.len());
buf[..len].copy_from_slice(&buffer[..len]);
buffer.drain(..len);
Ok(len)
}
}
impl embedded_io::Write for MockUart {
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
self.write_buffer.borrow_mut().extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> Result<(), Self::Error> {
Ok(())
}
}
#[test]
fn frame_distance_request_roundtrip() {
let frame = Frame::distance_request();
let data = frame.raw_data();
assert_eq!(data, &[0x22, 0x00, 0x00, 0x22]);
let parsed = Frame::parse(*data).expect("should parse");
assert_eq!(parsed, frame);
}
#[test]
fn frame_distance_response_decode() {
let response = [0x22, 0x01, 0x2C, 0x4F];
let frame = Frame::parse(response).expect("should parse");
let distance = frame.decode_distance().expect("should decode");
assert_eq!(distance, 300);
}
#[test]
fn frame_temperature_response_decode() {
let response = [0x11, 0x00, 0xFF, 0x10];
let frame = Frame::parse(response).expect("should parse");
let temp = frame.decode_temperature().expect("should decode");
assert_eq!(temp, 25.5);
}
#[cfg(feature = "uart")]
mod uart_frame_tests {
use super::*;
#[test]
fn mock_uart_write_and_read() {
let mut uart = MockUart::new(vec![0x22, 0x01, 0x2C, 0x4F]);
let cmd = [0x22, 0x00, 0x00, 0x22];
embedded_io::Write::write(&mut uart, &cmd).expect("should write");
let mut buf = [0u8; 4];
uart.read_exact(&mut buf).expect("should read exact");
assert_eq!(buf, [0x22, 0x01, 0x2C, 0x4F]);
assert_eq!(uart.written_data(), vec![0x22, 0x00, 0x00, 0x22]);
}
#[test]
fn mock_uart_multiple_frames() {
let responses = vec![
0x22, 0x00, 0x64, 0x86, 0x22, 0x01, 0x2C, 0x4F, ];
let mut uart = MockUart::new(responses);
let mut buf1 = [0u8; 4];
uart.read_exact(&mut buf1).expect("should read first frame");
let frame1 = Frame::parse(buf1).expect("should parse");
assert_eq!(frame1.decode_distance(), Some(100));
let mut buf2 = [0u8; 4];
uart.read_exact(&mut buf2).expect("should read second frame");
let frame2 = Frame::parse(buf2).expect("should parse");
assert_eq!(frame2.decode_distance(), Some(300));
}
#[test]
fn mock_uart_partial_read() {
let mut uart = MockUart::new(vec![0x22, 0x01, 0x2C]);
let mut buf = [0u8; 4];
let n = embedded_io::Read::read(&mut uart, &mut buf[..3])
.expect("should read partial frame");
assert_eq!(n, 3);
assert_eq!(&buf[..3], &[0x22, 0x01, 0x2C]);
}
}