use crate::protocol::command::{raw_payload, transfer_payload};
use crate::types::{Direction, Setup, TransferStatus};
#[test]
fn raw_payload_bytes() {
assert_eq!(
raw_payload(3, Direction::IN, &[0x00, 0x01, 0x00, 0x00]),
vec![0x03, 0x01, 0x00, 0x01, 0x00, 0x00]
);
assert_eq!(raw_payload(0x82, Direction::OUT, &[]), vec![0x02, 0x02]);
}
#[test]
fn setup_bytes_are_little_endian() {
let s = Setup::new(0x80, 0x06, 0x0100, 0x0000, 18);
assert_eq!(
s.to_bytes(),
[0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x12, 0x00]
);
assert!(s.is_in());
assert!(!Setup::new(0x00, 0x09, 0, 0, 0).is_in()); }
#[test]
fn transfer_payload_bytes() {
let s = Setup::new(0x80, 0x06, 0x0100, 0x0000, 18);
assert_eq!(
transfer_payload(0, s, &[]),
vec![0x00, 0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x12, 0x00]
);
let out = Setup::new(0x00, 0x09, 0x0200, 0x0000, 2);
assert_eq!(
transfer_payload(0, out, &[0xAA, 0xBB]),
vec![
0x00, 0x00, 0x09, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0xAA, 0xBB
]
);
}
#[test]
fn transfer_status_wire() {
assert_eq!(TransferStatus::from_u8(0x00), TransferStatus::Ok);
assert_eq!(TransferStatus::from_u8(0xFD), TransferStatus::Stall);
assert_eq!(TransferStatus::from_u8(0xFE), TransferStatus::Nak);
assert_eq!(TransferStatus::from_u8(0xFF), TransferStatus::NoDevice);
assert_eq!(TransferStatus::from_u8(0xFC), TransferStatus::Refused);
assert_eq!(TransferStatus::from_u8(0x42), TransferStatus::Other(0x42));
assert!(TransferStatus::Ok.is_ok());
assert!(!TransferStatus::Stall.is_ok());
assert_eq!(TransferStatus::Refused.as_u8(), 0xFC);
assert_eq!(TransferStatus::Other(0x42).as_u8(), 0x42);
}
#[cfg(feature = "mock")]
mod mock_roundtrip {
use crate::error::Error;
use crate::types::{Direction, Setup, TransferStatus};
use crate::{Device, FrameType, MockBox};
#[test]
fn raw_sends_without_reading_the_opt_in() {
let mock = MockBox::new(); let device = Device::with_mock(mock.clone());
device.raw(1, Direction::IN, &[0x00]).unwrap();
assert!(mock.saw(FrameType::Raw));
assert!(!mock.saw(FrameType::Query));
}
#[test]
fn raw_sends_when_allowed() {
let mock = MockBox::new().with_imperfect(true);
let device = Device::with_mock(mock.clone());
device
.raw(1, Direction::IN, &[0x00, 0x01, 0x00, 0x00])
.unwrap();
assert!(mock.saw(FrameType::Raw));
}
#[test]
fn raw_rejects_a_direction_that_is_not_a_flow() {
let device = Device::with_mock(MockBox::new().with_imperfect(true));
assert!(matches!(
device.raw(1, Direction::Both, &[0x00]),
Err(Error::RawDirection { .. })
));
assert!(matches!(
device.raw(1, Direction::With, &[0x00]),
Err(Error::RelativeDirection { .. })
));
}
#[test]
fn transfer_returns_the_devices_answer() {
let mock = MockBox::new()
.with_imperfect(true)
.with_transfer_reply(0x00, &[0x12, 0x01, 0x00, 0x02]);
let device = Device::with_mock(mock);
let reply = device
.transfer(0, Setup::new(0x80, 0x06, 0x0100, 0x0000, 18), &[])
.unwrap();
assert_eq!(reply.status, TransferStatus::Ok);
assert_eq!(reply.data(), &[0x12, 0x01, 0x00, 0x02]);
assert!(reply.is_ok());
}
#[test]
fn transfer_refused_when_opt_in_off() {
let device = Device::with_mock(MockBox::new());
let reply = device
.transfer(0, Setup::new(0x80, 0x06, 0x0100, 0x0000, 18), &[])
.unwrap();
assert_eq!(reply.status, TransferStatus::Refused);
assert!(reply.data().is_empty());
}
#[test]
fn transfer_carries_a_stall_status() {
let mock = MockBox::new()
.with_imperfect(true)
.with_transfer_reply(0xFD, &[]);
let device = Device::with_mock(mock);
let reply = device
.transfer(0, Setup::new(0x80, 0x06, 0x0100, 0x0000, 18), &[])
.unwrap();
assert_eq!(reply.status, TransferStatus::Stall);
assert!(!reply.is_ok());
}
#[test]
fn transfer_non_ok_status_carries_no_data() {
let mock = MockBox::new()
.with_imperfect(true)
.with_transfer_reply(0xFD, &[0x12, 0x01, 0x00, 0x02]);
let device = Device::with_mock(mock);
let reply = device
.transfer(0, Setup::new(0x80, 0x06, 0x0100, 0x0000, 18), &[])
.unwrap();
assert_eq!(reply.status, TransferStatus::Stall);
assert!(reply.data().is_empty(), "a non-OK transfer carries no data");
}
}