mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-12-22 13:45:20 +00:00
devices: serial: Make the serial unit tests pass
Some refactoring has taken place since the unit tests were written: The read/write in BusDevice now take a base address and the interrupt handling code has changed necessitating the need for a new TestInterrupt struct. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
9e372a8e48
commit
224f77500c
@ -173,13 +173,13 @@ mod tests {
|
||||
|
||||
struct ConstantDevice;
|
||||
impl BusDevice for ConstantDevice {
|
||||
fn read(&mut self, offset: u64, data: &mut [u8]) {
|
||||
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
|
||||
for (i, v) in data.iter_mut().enumerate() {
|
||||
*v = (offset as u8) + (i as u8);
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&mut self, offset: u64, data: &[u8]) {
|
||||
fn write(&mut self, _base: u64, offset: u64, data: &[u8]) {
|
||||
for (i, v) in data.iter().enumerate() {
|
||||
assert_eq!(*v, (offset as u8) + (i as u8))
|
||||
}
|
||||
|
@ -233,6 +233,23 @@ mod tests {
|
||||
use super::*;
|
||||
use std::io;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use vmm_sys_util::EventFd;
|
||||
|
||||
struct TestInterrupt {
|
||||
event_fd: EventFd,
|
||||
}
|
||||
|
||||
impl Interrupt for TestInterrupt {
|
||||
fn deliver(&self) -> result::Result<(), std::io::Error> {
|
||||
self.event_fd.write(1)
|
||||
}
|
||||
}
|
||||
|
||||
impl TestInterrupt {
|
||||
fn new(event_fd: EventFd) -> Self {
|
||||
TestInterrupt { event_fd }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct SharedBuffer {
|
||||
@ -258,15 +275,17 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn serial_output() {
|
||||
let intr_evt = EventFd::new().unwrap();
|
||||
let intr_evt = EventFd::new(0).unwrap();
|
||||
let serial_out = SharedBuffer::new();
|
||||
let mut serial = Serial::new_out(
|
||||
Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
|
||||
Box::new(serial_out.clone()),
|
||||
);
|
||||
|
||||
let mut serial = Serial::new_out(intr_evt, Box::new(serial_out.clone()));
|
||||
|
||||
serial.write(DATA as u64, &['x' as u8, 'y' as u8]);
|
||||
serial.write(DATA as u64, &['a' as u8]);
|
||||
serial.write(DATA as u64, &['b' as u8]);
|
||||
serial.write(DATA as u64, &['c' as u8]);
|
||||
serial.write(0, DATA as u64, &['x' as u8, 'y' as u8]);
|
||||
serial.write(0, DATA as u64, &['a' as u8]);
|
||||
serial.write(0, DATA as u64, &['b' as u8]);
|
||||
serial.write(0, DATA as u64, &['c' as u8]);
|
||||
assert_eq!(
|
||||
serial_out.buf.lock().unwrap().as_slice(),
|
||||
&['a' as u8, 'b' as u8, 'c' as u8]
|
||||
@ -275,16 +294,17 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn serial_input() {
|
||||
let intr_evt = EventFd::new().unwrap();
|
||||
let intr_evt = EventFd::new(0).unwrap();
|
||||
let serial_out = SharedBuffer::new();
|
||||
|
||||
let mut serial =
|
||||
Serial::new_out(intr_evt.try_clone().unwrap(), Box::new(serial_out.clone()));
|
||||
let mut serial = Serial::new_out(
|
||||
Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap())),
|
||||
Box::new(serial_out.clone()),
|
||||
);
|
||||
|
||||
// write 1 to the interrupt event fd, so that read doesn't block in case the event fd
|
||||
// counter doesn't change (for 0 it blocks)
|
||||
assert!(intr_evt.write(1).is_ok());
|
||||
serial.write(IER as u64, &[IER_RECV_BIT]);
|
||||
serial.write(0, IER as u64, &[IER_RECV_BIT]);
|
||||
serial
|
||||
.queue_input_bytes(&['a' as u8, 'b' as u8, 'c' as u8])
|
||||
.unwrap();
|
||||
@ -293,90 +313,97 @@ mod tests {
|
||||
|
||||
// check if reading in a 2-length array doesn't have side effects
|
||||
let mut data = [0u8, 0u8];
|
||||
serial.read(DATA as u64, &mut data[..]);
|
||||
serial.read(0, DATA as u64, &mut data[..]);
|
||||
assert_eq!(data, [0u8, 0u8]);
|
||||
|
||||
let mut data = [0u8];
|
||||
serial.read(LSR as u64, &mut data[..]);
|
||||
serial.read(0, LSR as u64, &mut data[..]);
|
||||
assert_ne!(data[0] & LSR_DATA_BIT, 0);
|
||||
serial.read(DATA as u64, &mut data[..]);
|
||||
serial.read(0, DATA as u64, &mut data[..]);
|
||||
assert_eq!(data[0], 'a' as u8);
|
||||
serial.read(DATA as u64, &mut data[..]);
|
||||
serial.read(0, DATA as u64, &mut data[..]);
|
||||
assert_eq!(data[0], 'b' as u8);
|
||||
serial.read(DATA as u64, &mut data[..]);
|
||||
serial.read(0, DATA as u64, &mut data[..]);
|
||||
assert_eq!(data[0], 'c' as u8);
|
||||
|
||||
// check if reading from the largest u8 offset returns 0
|
||||
serial.read(0xff, &mut data[..]);
|
||||
serial.read(0, 0xff, &mut data[..]);
|
||||
assert_eq!(data[0], 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serial_thr() {
|
||||
let intr_evt = EventFd::new().unwrap();
|
||||
let mut serial = Serial::new_sink(intr_evt.try_clone().unwrap());
|
||||
let intr_evt = EventFd::new(0).unwrap();
|
||||
let mut serial =
|
||||
Serial::new_sink(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap())));
|
||||
|
||||
// write 1 to the interrupt event fd, so that read doesn't block in case the event fd
|
||||
// counter doesn't change (for 0 it blocks)
|
||||
assert!(intr_evt.write(1).is_ok());
|
||||
serial.write(IER as u64, &[IER_THR_BIT]);
|
||||
serial.write(DATA as u64, &['a' as u8]);
|
||||
serial.write(0, IER as u64, &[IER_THR_BIT]);
|
||||
serial.write(0, DATA as u64, &['a' as u8]);
|
||||
|
||||
assert_eq!(intr_evt.read().unwrap(), 2);
|
||||
let mut data = [0u8];
|
||||
serial.read(IER as u64, &mut data[..]);
|
||||
serial.read(0, IER as u64, &mut data[..]);
|
||||
assert_eq!(data[0] & IER_FIFO_BITS, IER_THR_BIT);
|
||||
serial.read(IIR as u64, &mut data[..]);
|
||||
serial.read(0, IIR as u64, &mut data[..]);
|
||||
assert_ne!(data[0] & IIR_THR_BIT, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serial_dlab() {
|
||||
let mut serial = Serial::new_sink(EventFd::new().unwrap());
|
||||
let intr_evt = EventFd::new(0).unwrap();
|
||||
let mut serial =
|
||||
Serial::new_sink(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap())));
|
||||
|
||||
serial.write(LCR as u64, &[LCR_DLAB_BIT as u8]);
|
||||
serial.write(DLAB_LOW as u64, &[0x12 as u8]);
|
||||
serial.write(DLAB_HIGH as u64, &[0x34 as u8]);
|
||||
serial.write(0, LCR as u64, &[LCR_DLAB_BIT as u8]);
|
||||
serial.write(0, DLAB_LOW as u64, &[0x12 as u8]);
|
||||
serial.write(0, DLAB_HIGH as u64, &[0x34 as u8]);
|
||||
|
||||
let mut data = [0u8];
|
||||
serial.read(LCR as u64, &mut data[..]);
|
||||
serial.read(0, LCR as u64, &mut data[..]);
|
||||
assert_eq!(data[0], LCR_DLAB_BIT as u8);
|
||||
serial.read(DLAB_LOW as u64, &mut data[..]);
|
||||
serial.read(0, DLAB_LOW as u64, &mut data[..]);
|
||||
assert_eq!(data[0], 0x12);
|
||||
serial.read(DLAB_HIGH as u64, &mut data[..]);
|
||||
serial.read(0, DLAB_HIGH as u64, &mut data[..]);
|
||||
assert_eq!(data[0], 0x34);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serial_modem() {
|
||||
let mut serial = Serial::new_sink(EventFd::new().unwrap());
|
||||
let intr_evt = EventFd::new(0).unwrap();
|
||||
let mut serial =
|
||||
Serial::new_sink(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap())));
|
||||
|
||||
serial.write(MCR as u64, &[MCR_LOOP_BIT as u8]);
|
||||
serial.write(DATA as u64, &['a' as u8]);
|
||||
serial.write(DATA as u64, &['b' as u8]);
|
||||
serial.write(DATA as u64, &['c' as u8]);
|
||||
serial.write(0, MCR as u64, &[MCR_LOOP_BIT as u8]);
|
||||
serial.write(0, DATA as u64, &['a' as u8]);
|
||||
serial.write(0, DATA as u64, &['b' as u8]);
|
||||
serial.write(0, DATA as u64, &['c' as u8]);
|
||||
|
||||
let mut data = [0u8];
|
||||
serial.read(MSR as u64, &mut data[..]);
|
||||
serial.read(0, MSR as u64, &mut data[..]);
|
||||
assert_eq!(data[0], DEFAULT_MODEM_STATUS as u8);
|
||||
serial.read(MCR as u64, &mut data[..]);
|
||||
serial.read(0, MCR as u64, &mut data[..]);
|
||||
assert_eq!(data[0], MCR_LOOP_BIT as u8);
|
||||
serial.read(DATA as u64, &mut data[..]);
|
||||
serial.read(0, DATA as u64, &mut data[..]);
|
||||
assert_eq!(data[0], 'a' as u8);
|
||||
serial.read(DATA as u64, &mut data[..]);
|
||||
serial.read(0, DATA as u64, &mut data[..]);
|
||||
assert_eq!(data[0], 'b' as u8);
|
||||
serial.read(DATA as u64, &mut data[..]);
|
||||
serial.read(0, DATA as u64, &mut data[..]);
|
||||
assert_eq!(data[0], 'c' as u8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serial_scratch() {
|
||||
let mut serial = Serial::new_sink(EventFd::new().unwrap());
|
||||
let intr_evt = EventFd::new(0).unwrap();
|
||||
let mut serial =
|
||||
Serial::new_sink(Box::new(TestInterrupt::new(intr_evt.try_clone().unwrap())));
|
||||
|
||||
serial.write(SCR as u64, &[0x12 as u8]);
|
||||
serial.write(0, SCR as u64, &[0x12 as u8]);
|
||||
|
||||
let mut data = [0u8];
|
||||
serial.read(SCR as u64, &mut data[..]);
|
||||
serial.read(0, SCR as u64, &mut data[..]);
|
||||
assert_eq!(data[0], 0x12 as u8);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user