mirror of
https://github.com/rust-vmm/vhost-device.git
synced 2026-01-02 05:53:33 +00:00
sound: Add Test for vhost-device-sound
This PR adds test for uncovered code paths Signed-off-by: Dorinda Bassey <dbassey@redhat.com>
This commit is contained in:
parent
8e1e0a7a2a
commit
31212150c1
@ -1,5 +1,5 @@
|
||||
{
|
||||
"coverage_score": 56.58,
|
||||
"coverage_score": 60.27,
|
||||
"exclude_path": "",
|
||||
"crate_features": ""
|
||||
}
|
||||
|
||||
@ -922,7 +922,59 @@ mod tests {
|
||||
let vring = VringRwLock::new(mem, 0x1000).unwrap();
|
||||
vring.set_queue_info(0x100, 0x200, 0x300).unwrap();
|
||||
vring.set_queue_ready(true);
|
||||
t.process_control(&vring, &audio_backend).unwrap();
|
||||
|
||||
// Test control msgs with three descriptors
|
||||
let ctrl_msg_descs = [
|
||||
ControlMessageKind::PcmInfo,
|
||||
ControlMessageKind::ChmapInfo,
|
||||
ControlMessageKind::JackInfo,
|
||||
];
|
||||
for code in ctrl_msg_descs {
|
||||
let req = VirtioSoundHeader {
|
||||
code: Le32::from(code as u32),
|
||||
};
|
||||
let addr_req = 0x10_0000;
|
||||
let descs = [
|
||||
Descriptor::new(addr_req, 0x100, 0, 0), // request
|
||||
Descriptor::new(0x20_0000, 0x100, VRING_DESC_F_WRITE as u16, 0),
|
||||
Descriptor::new(0x20_0000, 0x100, VRING_DESC_F_WRITE as u16, 0), // response
|
||||
];
|
||||
|
||||
let (vring, mem) = setup_descs(&descs);
|
||||
mem.memory()
|
||||
.write_obj(req, GuestAddress(addr_req))
|
||||
.expect("writing to succeed");
|
||||
t.mem = Some(mem.clone());
|
||||
t.process_control(&vring, &audio_backend).unwrap();
|
||||
}
|
||||
|
||||
// Test control msgs with two descriptors
|
||||
let ctrl_descs = [
|
||||
ControlMessageKind::JackRemap,
|
||||
ControlMessageKind::PcmSetParams,
|
||||
ControlMessageKind::PcmPrepare,
|
||||
ControlMessageKind::PcmRelease,
|
||||
ControlMessageKind::PcmStart,
|
||||
ControlMessageKind::PcmStop,
|
||||
];
|
||||
for code in ctrl_descs {
|
||||
let req = VirtioSoundHeader {
|
||||
code: Le32::from(code as u32),
|
||||
};
|
||||
let addr_req = 0x10_0000;
|
||||
let descs = [
|
||||
Descriptor::new(addr_req, 0x100, 0, 0), // request
|
||||
Descriptor::new(0x20_0000, 0x100, VRING_DESC_F_WRITE as u16, 0),
|
||||
];
|
||||
|
||||
let (vring, mem) = setup_descs(&descs);
|
||||
mem.memory()
|
||||
.write_obj(req, GuestAddress(addr_req))
|
||||
.expect("writing to succeed");
|
||||
t.mem = Some(mem.clone());
|
||||
t.process_control(&vring, &audio_backend).unwrap();
|
||||
}
|
||||
|
||||
t.process_io(&vring, &audio_backend, Direction::Output)
|
||||
.unwrap();
|
||||
t.process_io(&vring, &audio_backend, Direction::Input)
|
||||
|
||||
@ -212,6 +212,7 @@ impl TryFrom<Le32> for ControlMessageKind {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(test, derive(Clone))]
|
||||
pub struct ControlMessage {
|
||||
pub kind: ControlMessageKind,
|
||||
pub code: u32,
|
||||
@ -382,10 +383,77 @@ pub fn start_backend_server(config: SoundConfig) {
|
||||
mod tests {
|
||||
use std::sync::Arc;
|
||||
|
||||
use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap};
|
||||
use vhost_user_backend::{VringRwLock, VringT};
|
||||
use virtio_bindings::bindings::virtio_ring::{VRING_DESC_F_NEXT, VRING_DESC_F_WRITE};
|
||||
use virtio_queue::{mock::MockSplitQueue, Descriptor, Queue, QueueOwnedT};
|
||||
use vm_memory::{
|
||||
Address, ByteValued, GuestAddress, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap,
|
||||
};
|
||||
|
||||
use super::*;
|
||||
use crate::ControlMessageKind;
|
||||
use crate::{ControlMessageKind, SoundDescriptorChain};
|
||||
|
||||
// Prepares a single chain of descriptors
|
||||
fn prepare_desc_chain<R: ByteValued>(
|
||||
start_addr: GuestAddress,
|
||||
hdr: R,
|
||||
response_len: u32,
|
||||
) -> SoundDescriptorChain {
|
||||
let mem = &GuestMemoryMmap::<()>::from_ranges(&[(start_addr, 0x1000)]).unwrap();
|
||||
let vq = MockSplitQueue::new(mem, 16);
|
||||
let mut next_addr = vq.desc_table().total_size() + 0x100;
|
||||
let mut index = 0;
|
||||
|
||||
let desc_out = Descriptor::new(
|
||||
next_addr,
|
||||
std::mem::size_of::<R>() as u32,
|
||||
VRING_DESC_F_NEXT as u16,
|
||||
index + 1,
|
||||
);
|
||||
|
||||
mem.write_obj::<R>(hdr, desc_out.addr()).unwrap();
|
||||
vq.desc_table().store(index, desc_out).unwrap();
|
||||
next_addr += u64::from(desc_out.len());
|
||||
index += 1;
|
||||
|
||||
// In response descriptor
|
||||
let desc_in = Descriptor::new(next_addr, response_len, VRING_DESC_F_WRITE as u16, 0);
|
||||
vq.desc_table().store(index, desc_in).unwrap();
|
||||
|
||||
// Put the descriptor index 0 in the first available ring position.
|
||||
mem.write_obj(0u16, vq.avail_addr().unchecked_add(4))
|
||||
.unwrap();
|
||||
|
||||
// Set `avail_idx` to 1.
|
||||
mem.write_obj(1u16, vq.avail_addr().unchecked_add(2))
|
||||
.unwrap();
|
||||
|
||||
// Create descriptor chain from pre-filled memory
|
||||
vq.create_queue::<Queue>()
|
||||
.unwrap()
|
||||
.iter(GuestMemoryAtomic::new(mem.clone()).memory())
|
||||
.unwrap()
|
||||
.next()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn ctrl_msg() -> ControlMessage {
|
||||
let hdr = VirtioSndPcmSetParams::default();
|
||||
let memr = GuestMemoryAtomic::new(
|
||||
GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap(),
|
||||
);
|
||||
let vring = VringRwLock::new(memr, 0x1000).unwrap();
|
||||
let mem = &GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
let vq = MockSplitQueue::new(mem, 16);
|
||||
let next_addr = vq.desc_table().total_size() + 0x100;
|
||||
ControlMessage {
|
||||
kind: ControlMessageKind::JackInfo,
|
||||
code: 0,
|
||||
desc_chain: prepare_desc_chain::<VirtioSndPcmSetParams>(GuestAddress(0), hdr, 1),
|
||||
descriptor: Descriptor::new(next_addr, 0x200, VRING_DESC_F_NEXT as u16, 1),
|
||||
vring,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sound_server() {
|
||||
@ -439,4 +507,41 @@ mod tests {
|
||||
Err(InvalidControlMessage(invalid_value))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_valid_output() {
|
||||
let val = virtio_sound::VIRTIO_SND_D_OUTPUT;
|
||||
assert_eq!(Direction::try_from(val).unwrap(), Direction::Output);
|
||||
|
||||
let val = virtio_sound::VIRTIO_SND_D_INPUT;
|
||||
assert_eq!(Direction::try_from(val).unwrap(), Direction::Input);
|
||||
|
||||
let val = 42;
|
||||
Direction::try_from(val).unwrap_err();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_display() {
|
||||
let error = InvalidControlMessage(42);
|
||||
let formatted_error = format!("{}", error);
|
||||
assert_eq!(formatted_error, "Invalid control message code 42");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_into_error() {
|
||||
let error = InvalidControlMessage(42);
|
||||
let _error: Error = error.into();
|
||||
|
||||
// Test from stream Error
|
||||
let stream_error = stream::Error::DescriptorReadFailed;
|
||||
let _error: Error = stream_error.into();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_debug_format() {
|
||||
let ctrl_msg = ctrl_msg();
|
||||
let debug_output = format!("{:?}", ctrl_msg);
|
||||
let expected_output = "ControlMessage { kind: JackInfo, code: 0 }".to_string();
|
||||
assert_eq!(debug_output, expected_output);
|
||||
}
|
||||
}
|
||||
|
||||
@ -335,6 +335,8 @@ impl Drop for Buffer {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::fmt::Write;
|
||||
|
||||
use vhost_user_backend::{VringRwLock, VringT};
|
||||
use virtio_bindings::bindings::virtio_ring::{VRING_DESC_F_NEXT, VRING_DESC_F_WRITE};
|
||||
use virtio_queue::{mock::MockSplitQueue, Descriptor, Queue, QueueOwnedT};
|
||||
@ -408,6 +410,28 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_display_fmt() {
|
||||
assert_eq!(&PCMState::Stop.to_string(), "VIRTIO_SND_R_PCM_STOP");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_logging() {
|
||||
let data_descriptor = Descriptor::new(0, 0, 0, 0);
|
||||
let msg = iomsg();
|
||||
let message = Arc::new(msg);
|
||||
let direction = Direction::Input;
|
||||
let buffer = Buffer::new(data_descriptor, message, direction);
|
||||
assert_eq!(format!("{direction:?}"), "Input");
|
||||
assert_eq!(
|
||||
format!("{buffer:?}"),
|
||||
format!(
|
||||
"Buffer {{ pos: 0, direction: Input, message: {:?} }}",
|
||||
&Arc::as_ptr(&buffer.message)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pcm_state_transitions() {
|
||||
let mut state = PCMState::new();
|
||||
@ -546,4 +570,47 @@ mod tests {
|
||||
let mut buf = vec![0; 5];
|
||||
buffer.read_output(&mut buf).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_buffer_write_input() {
|
||||
let msg = iomsg();
|
||||
let message = Arc::new(msg);
|
||||
let desc_msg = iomsg();
|
||||
let mut buffer = Buffer::new(
|
||||
desc_msg.desc_chain.clone().readable().next().unwrap(),
|
||||
message,
|
||||
Direction::Input,
|
||||
);
|
||||
|
||||
let buf = vec![0; 5];
|
||||
buffer.write_input(&buf).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_buffer_fn() {
|
||||
let data_descriptor = Descriptor::new(0, 0, 0, 0);
|
||||
let msg = iomsg();
|
||||
let message = Arc::new(msg);
|
||||
let direction = Direction::Input;
|
||||
let buffer = Buffer::new(data_descriptor, message, direction);
|
||||
|
||||
assert_eq!(buffer.desc_len() as usize, buffer.pos);
|
||||
assert_eq!(buffer.desc_len(), 0);
|
||||
assert_eq!(buffer.direction, Direction::Input);
|
||||
|
||||
// Test debug format representation for Buffer
|
||||
let mut debug_output = String::new();
|
||||
|
||||
// Format the Debug representation into the String.
|
||||
write!(&mut debug_output, "{:?}", buffer).unwrap();
|
||||
|
||||
let expected_debug = format!(
|
||||
"Buffer {{ pos: {}, direction: {:?}, message: {:?} }}",
|
||||
buffer.pos,
|
||||
buffer.direction,
|
||||
Arc::as_ptr(&buffer.message)
|
||||
);
|
||||
|
||||
assert_eq!(debug_output, expected_debug);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user