use embedded_hal::blocking::spi;
use embedded_hal::spi::FullDuplex;
use nb;
use crate::common::Generic;
use crate::error::MockError;
#[derive(Clone, Debug, PartialEq)]
pub enum Mode {
Write,
Transfer,
Send,
Read,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Transaction {
expected_mode: Mode,
expected_data: Vec<u8>,
response: Vec<u8>,
}
impl Transaction {
pub fn write(expected: Vec<u8>) -> Transaction {
Transaction {
expected_mode: Mode::Write,
expected_data: expected,
response: Vec::new(),
}
}
pub fn transfer(expected: Vec<u8>, response: Vec<u8>) -> Transaction {
Transaction {
expected_mode: Mode::Transfer,
expected_data: expected,
response,
}
}
pub fn send(expected: u8) -> Transaction {
Transaction {
expected_mode: Mode::Send,
expected_data: [expected].to_vec(),
response: Vec::new(),
}
}
pub fn read(response: u8) -> Transaction {
Transaction {
expected_mode: Mode::Read,
expected_data: Vec::new(),
response: [response].to_vec(),
}
}
}
pub type Mock = Generic<Transaction>;
impl spi::Write<u8> for Mock {
type Error = MockError;
fn write(&mut self, buffer: &[u8]) -> Result<(), Self::Error> {
let w = self.next().expect("no expectation for spi::write call");
assert_eq!(w.expected_mode, Mode::Write, "spi::write unexpected mode");
assert_eq!(
&w.expected_data, &buffer,
"spi::write data does not match expectation"
);
Ok(())
}
}
impl FullDuplex<u8> for Mock {
type Error = MockError;
fn send(&mut self, buffer: u8) -> nb::Result<(), Self::Error> {
let data = self.next().expect("no expectation for spi::send call");
assert_eq!(data.expected_mode, Mode::Send, "spi::send unexpected mode");
assert_eq!(
data.expected_data[0], buffer,
"spi::send data does not match expectation"
);
Ok(())
}
fn read(&mut self) -> nb::Result<u8, Self::Error> {
let w = self.next().expect("no expectation for spi::read call");
assert_eq!(w.expected_mode, Mode::Read, "spi::Read unexpected mode");
assert_eq!(
1,
w.response.len(),
"mismatched response length for spi::read"
);
let buffer: u8 = w.response[0];
Ok(buffer)
}
}
impl spi::Transfer<u8> for Mock {
type Error = MockError;
fn transfer<'w>(&mut self, buffer: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
let w = self.next().expect("no expectation for spi::transfer call");
assert_eq!(
w.expected_mode,
Mode::Transfer,
"spi::transfer unexpected mode"
);
assert_eq!(
&w.expected_data, &buffer,
"spi::write data does not match expectation"
);
assert_eq!(
buffer.len(),
w.response.len(),
"mismatched response length for spi::transfer"
);
buffer.copy_from_slice(&w.response);
Ok(buffer)
}
}
#[cfg(test)]
mod test {
use super::*;
use embedded_hal::blocking::spi::{Transfer, Write};
#[test]
fn test_spi_mock_send() {
let mut spi = Mock::new(&[Transaction::send(10)]);
let _ = spi.send(10).unwrap();
spi.done();
}
#[test]
fn test_spi_mock_read() {
let mut spi = Mock::new(&[Transaction::read(10)]);
let ans = spi.read().unwrap();
assert_eq!(ans, 10);
spi.done();
}
#[test]
fn test_spi_mock_multiple1() {
let expectations = [
Transaction::write(vec![1, 2]),
Transaction::send(9),
Transaction::read(10),
Transaction::send(0xFE),
Transaction::read(0xFF),
Transaction::transfer(vec![3, 4], vec![5, 6]),
];
let mut spi = Mock::new(&expectations);
spi.write(&vec![1, 2]).unwrap();
let _ = spi.send(0x09);
assert_eq!(spi.read().unwrap(), 0x0a);
let _ = spi.send(0xfe);
assert_eq!(spi.read().unwrap(), 0xFF);
let mut v = vec![3, 4];
spi.transfer(&mut v).unwrap();
assert_eq!(v, vec![5, 6]);
spi.done();
}
#[test]
fn test_spi_mock_write() {
let expectations = [Transaction::write(vec![10, 12])];
let mut spi = Mock::new(&expectations);
spi.write(&vec![10, 12]).unwrap();
spi.done();
}
#[test]
fn test_spi_mock_transfer() {
let expectations = [Transaction::transfer(vec![10, 12], vec![12, 13])];
let mut spi = Mock::new(&expectations);
let mut v = vec![10, 12];
spi.transfer(&mut v).unwrap();
assert_eq!(v, vec![12, 13]);
spi.done();
}
#[test]
fn test_spi_mock_multiple() {
let expectations = [
Transaction::write(vec![1, 2]),
Transaction::transfer(vec![3, 4], vec![5, 6]),
];
let mut spi = Mock::new(&expectations);
spi.write(&vec![1, 2]).unwrap();
let mut v = vec![3, 4];
spi.transfer(&mut v).unwrap();
assert_eq!(v, vec![5, 6]);
spi.done();
}
#[test]
#[should_panic]
fn test_spi_mock_write_err() {
let expectations = [Transaction::write(vec![10, 12])];
let mut spi = Mock::new(&expectations);
spi.write(&vec![10, 12, 12]).unwrap();
spi.done();
}
#[test]
#[should_panic]
fn test_spi_mock_transfer_err() {
let expectations = [Transaction::transfer(vec![10, 12], vec![12, 15])];
let mut spi = Mock::new(&expectations);
let mut v = vec![10, 12];
spi.transfer(&mut v).unwrap();
assert_eq!(v, vec![12, 13]);
spi.done();
}
#[test]
#[should_panic]
fn test_spi_mock_transfer_response_err() {
let expectations = [Transaction::transfer(vec![1, 2], vec![3, 4, 5])];
let mut spi = Mock::new(&expectations);
let mut v = vec![10, 12];
spi.transfer(&mut v).unwrap();
assert_eq!(v, vec![12, 13]);
spi.done();
}
#[test]
#[should_panic]
fn test_spi_mock_mode_err() {
let expectations = [Transaction::transfer(vec![10, 12], vec![])];
let mut spi = Mock::new(&expectations);
spi.write(&vec![10, 12, 12]).unwrap();
spi.done();
}
#[test]
#[should_panic]
fn test_spi_mock_multiple_transaction_err() {
let expectations = [
Transaction::write(vec![10, 12]),
Transaction::write(vec![10, 12]),
];
let mut spi = Mock::new(&expectations);
spi.write(&vec![10, 12, 12]).unwrap();
spi.done();
}
}