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:
Rob Bradford 2019-07-16 10:27:31 +01:00 committed by Samuel Ortiz
parent 9e372a8e48
commit 224f77500c
2 changed files with 73 additions and 46 deletions

View File

@ -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))
}

View File

@ -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);
}
}