Răsfoiți Sursa

Add tests for notifying device about queue.

These cover suppressing notifications either using flags or with
avail_event.
Andrew Walbran 1 an în urmă
părinte
comite
961938ab19
1 a modificat fișierele cu 83 adăugiri și 1 ștergeri
  1. 83 1
      src/queue.rs

+ 83 - 1
src/queue.rs

@@ -939,10 +939,16 @@ pub(crate) fn fake_read_write_queue<const QUEUE_SIZE: usize>(
 mod tests {
     use super::*;
     use crate::{
+        device::common::Feature,
         hal::fake::FakeHal,
-        transport::mmio::{MmioTransport, VirtIOHeader, MODERN_VERSION},
+        transport::{
+            fake::{FakeTransport, QueueStatus, State},
+            mmio::{MmioTransport, VirtIOHeader, MODERN_VERSION},
+            DeviceStatus, DeviceType,
+        },
     };
     use core::ptr::NonNull;
+    use std::sync::{Arc, Mutex};
 
     #[test]
     fn invalid_queue_size() {
@@ -1111,4 +1117,80 @@ mod tests {
             assert_eq!((*indirect_descriptors)[3].flags, DescFlags::WRITE);
         }
     }
+
+    /// Tests that the queue notifies the device about added buffers, if it hasn't suppressed
+    /// notifications.
+    #[test]
+    fn add_notify() {
+        let mut config_space = ();
+        let state = Arc::new(Mutex::new(State {
+            queues: vec![QueueStatus::default()],
+            ..Default::default()
+        }));
+        let mut transport = FakeTransport {
+            device_type: DeviceType::Block,
+            max_queue_size: 4,
+            device_features: 0,
+            config_space: NonNull::from(&mut config_space),
+            state: state.clone(),
+        };
+        let mut queue = VirtQueue::<FakeHal, 4>::new(&mut transport, 0, false, false).unwrap();
+
+        // Add a buffer chain with a single device-readable part.
+        unsafe { queue.add(&[&[42]], &mut []) }.unwrap();
+
+        // Check that the transport would be notified.
+        assert_eq!(queue.should_notify(), true);
+
+        // SAFETY: the various parts of the queue are properly aligned, dereferenceable and
+        // initialised, and nothing else is accessing them at the same time.
+        unsafe {
+            // Suppress notifications.
+            (*queue.used.as_ptr()).flags = 0x01;
+        }
+
+        // Check that the transport would not be notified.
+        assert_eq!(queue.should_notify(), false);
+    }
+
+    /// Tests that the queue notifies the device about added buffers, if it hasn't suppressed
+    /// notifications with the `avail_event` index.
+    #[test]
+    fn add_notify_event_idx() {
+        let mut config_space = ();
+        let state = Arc::new(Mutex::new(State {
+            queues: vec![QueueStatus::default()],
+            ..Default::default()
+        }));
+        let mut transport = FakeTransport {
+            device_type: DeviceType::Block,
+            max_queue_size: 4,
+            device_features: Feature::RING_EVENT_IDX.bits(),
+            config_space: NonNull::from(&mut config_space),
+            state: state.clone(),
+        };
+        let mut queue = VirtQueue::<FakeHal, 4>::new(&mut transport, 0, false, true).unwrap();
+
+        // Add a buffer chain with a single device-readable part.
+        assert_eq!(unsafe { queue.add(&[&[42]], &mut []) }.unwrap(), 0);
+
+        // Check that the transport would be notified.
+        assert_eq!(queue.should_notify(), true);
+
+        // SAFETY: the various parts of the queue are properly aligned, dereferenceable and
+        // initialised, and nothing else is accessing them at the same time.
+        unsafe {
+            // Suppress notifications.
+            (*queue.used.as_ptr()).avail_event = 1;
+        }
+
+        // Check that the transport would not be notified.
+        assert_eq!(queue.should_notify(), false);
+
+        // Add another buffer chain.
+        assert_eq!(unsafe { queue.add(&[&[42]], &mut []) }.unwrap(), 1);
+
+        // Check that the transport should be notified again now.
+        assert_eq!(queue.should_notify(), true);
+    }
 }