diff options
author | Jorge E. Moreira <jemoreira@google.com> | 2019-03-08 18:26:19 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2019-03-12 18:54:11 -0700 |
commit | ea8721ad1b68c0bf839b8aaa825e0046ee63db82 (patch) | |
tree | 0be6aa612c341d684c193ee67a37943ff76b8fee /devices/src/virtio/input/event_source.rs | |
parent | 49f071ad4f197e657ea4c497a677009d1788ff63 (diff) | |
download | crosvm-ea8721ad1b68c0bf839b8aaa825e0046ee63db82.tar crosvm-ea8721ad1b68c0bf839b8aaa825e0046ee63db82.tar.gz crosvm-ea8721ad1b68c0bf839b8aaa825e0046ee63db82.tar.bz2 crosvm-ea8721ad1b68c0bf839b8aaa825e0046ee63db82.tar.lz crosvm-ea8721ad1b68c0bf839b8aaa825e0046ee63db82.tar.xz crosvm-ea8721ad1b68c0bf839b8aaa825e0046ee63db82.tar.zst crosvm-ea8721ad1b68c0bf839b8aaa825e0046ee63db82.zip |
Add tests for virtio input device
These tests would have caught chromium:939585 Test=cargo test -p devices Change-Id: If980fe8b56b9d76e77b652fb727b8849dbedd9cc Reviewed-on: https://chromium-review.googlesource.com/1512759 Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com> Tested-by: kokoro <noreply+kokoro@google.com> Tested-by: Jorge Moreira Broche <jemoreira@google.com> Reviewed-by: Dylan Reid <dgreid@chromium.org>
Diffstat (limited to 'devices/src/virtio/input/event_source.rs')
-rw-r--r-- | devices/src/virtio/input/event_source.rs | 186 |
1 files changed, 185 insertions, 1 deletions
diff --git a/devices/src/virtio/input/event_source.rs b/devices/src/virtio/input/event_source.rs index d75f124..5e24f08 100644 --- a/devices/src/virtio/input/event_source.rs +++ b/devices/src/virtio/input/event_source.rs @@ -135,7 +135,7 @@ impl<T: AsRawFd> EventSourceImpl<T> { impl<T> EventSourceImpl<T> where - T: Read + Write + AsRawFd, + T: Read + Write, { // Receive events from the source and store them in a queue, unless they should be filtered out. fn receive_events<F: Fn(&input_event) -> bool>(&mut self, event_filter: F) -> Result<usize> { @@ -332,3 +332,187 @@ where self.evt_source_impl.available_events() } } + +#[cfg(test)] +mod tests { + use data_model::{DataInit, Le16, Le32}; + use std::cmp::min; + use std::io::Read; + use std::io::Write; + use std::mem::size_of; + use virtio::input::event_source::input_event; + use virtio::input::event_source::EventSourceImpl; + use virtio::input::virtio_input_event; + + struct SourceMock { + events: Vec<u8>, + } + + impl SourceMock { + fn new(evts: &Vec<input_event>) -> SourceMock { + let mut events: Vec<u8> = vec![]; + for evt in evts { + for byte in evt.as_slice() { + events.push(byte.clone()); + } + } + SourceMock { events } + } + } + + impl Read for SourceMock { + fn read(&mut self, buf: &mut [u8]) -> std::result::Result<usize, std::io::Error> { + let copy_size = min(buf.len(), self.events.len()); + buf[..copy_size].copy_from_slice(&self.events[..copy_size]); + Ok(copy_size) + } + } + impl Write for SourceMock { + fn write(&mut self, buf: &[u8]) -> std::result::Result<usize, std::io::Error> { + Ok(buf.len()) + } + + fn flush(&mut self) -> std::result::Result<(), std::io::Error> { + Ok(()) + } + } + + #[test] + fn empty_new() { + let mut source = EventSourceImpl::new(SourceMock::new(&vec![])); + assert_eq!( + source.available_events(), + 0, + "zero events should be available" + ); + let mut buffer = [0u8, 80]; + assert_eq!( + source.read(&mut buffer).unwrap(), + 0, + "zero events should be read" + ); + } + + #[test] + fn empty_receive() { + let mut source = EventSourceImpl::new(SourceMock::new(&vec![])); + assert_eq!( + source.receive_events(|_| true).unwrap(), + 0, + "zero events should be received" + ); + let mut buffer = [0u8, 80]; + assert_eq!( + source.read(&mut buffer).unwrap(), + 0, + "zero events should be read" + ); + } + + fn instantiate_input_events(count: usize) -> Vec<input_event> { + let mut ret: Vec<input_event> = Vec::with_capacity(count); + for idx in 0..count { + ret.push(input_event { + timestamp_fields: [0, 0], + type_: 3 * (idx as u16) + 1, + code: 3 * (idx as u16) + 2, + value: 3 * (idx as u32) + 3, + }); + } + ret + } + + fn assert_events_match(e1: &virtio_input_event, e2: &input_event) { + assert_eq!(e1.type_, Le16::from(e2.type_), "type should match"); + assert_eq!(e1.code, Le16::from(e2.code), "code should match"); + assert_eq!(e1.value, Le32::from(e2.value), "value should match"); + } + + #[test] + fn partial_read() { + let evts = instantiate_input_events(4usize); + let mut source = EventSourceImpl::new(SourceMock::new(&evts)); + assert_eq!( + source.receive_events(|_| true).unwrap(), + evts.len(), + "should receive all events" + ); + let mut evt = virtio_input_event { + type_: Le16::from(0), + code: Le16::from(0), + value: Le32::from(0), + }; + assert_eq!( + source.read(evt.as_mut_slice()).unwrap(), + virtio_input_event::EVENT_SIZE, + "should read a single event" + ); + assert_events_match(&evt, &evts[0]); + } + + #[test] + fn exact_read() { + const EVENT_COUNT: usize = 4; + let evts = instantiate_input_events(EVENT_COUNT); + let mut source = EventSourceImpl::new(SourceMock::new(&evts)); + assert_eq!( + source.receive_events(|_| true).unwrap(), + evts.len(), + "should receive all events" + ); + let mut vio_evts = [0u8; EVENT_COUNT * size_of::<virtio_input_event>()]; + assert_eq!( + source.read(&mut vio_evts).unwrap(), + EVENT_COUNT * virtio_input_event::EVENT_SIZE, + "should read all events" + ); + + let mut chunks = vio_evts.chunks_exact(virtio_input_event::EVENT_SIZE); + for idx in 0..EVENT_COUNT { + let evt = virtio_input_event::from_slice(chunks.next().unwrap()).unwrap(); + assert_events_match(&evt, &evts[idx]); + } + } + + #[test] + fn over_read() { + const EVENT_COUNT: usize = 4; + let evts = instantiate_input_events(EVENT_COUNT); + let mut source = EventSourceImpl::new(SourceMock::new(&evts)); + assert_eq!( + source.receive_events(|_| true).unwrap(), + evts.len(), + "should receive all events" + ); + let mut vio_evts = [0u8; 2 * EVENT_COUNT * size_of::<virtio_input_event>()]; + assert_eq!( + source.read(&mut vio_evts).unwrap(), + EVENT_COUNT * virtio_input_event::EVENT_SIZE, + "should only read available events" + ); + + let mut chunks = vio_evts.chunks_exact(virtio_input_event::EVENT_SIZE); + for idx in 0..EVENT_COUNT { + let evt = virtio_input_event::from_slice(chunks.next().unwrap()).unwrap(); + assert_events_match(&evt, &evts[idx]); + } + } + + #[test] + fn incomplete_read() { + const EVENT_COUNT: usize = 4; + let evts = instantiate_input_events(EVENT_COUNT); + let mut source = EventSourceImpl::new(SourceMock::new(&evts)); + assert_eq!( + source.receive_events(|_| true).unwrap(), + evts.len(), + "should receive all events" + ); + let mut vio_evts = [0u8; 3]; + assert_eq!( + source.read(&mut vio_evts).unwrap(), + 0, + "shouldn't read incomplete events" + ); + } +} |