mirror of
https://github.com/rust-vmm/vhost-device.git
synced 2026-01-03 07:02:17 +00:00
vhost-device-console: improve tests
Add tests for the new input events and increase overall test coverage. Signed-off-by: Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>
This commit is contained in:
parent
c7397703d4
commit
8e18b8b92b
@ -1,5 +1,5 @@
|
||||
{
|
||||
"coverage_score": 80.31,
|
||||
"coverage_score": 86.38,
|
||||
"exclude_path": "",
|
||||
"crate_features": ""
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ impl VuConsoleConfig {
|
||||
}
|
||||
}
|
||||
|
||||
// This is the public API through which an external program starts the
|
||||
/// This is the public API through which an external program starts the
|
||||
/// vhost-device-console backend server.
|
||||
pub(crate) fn start_backend_server(
|
||||
socket: PathBuf,
|
||||
@ -240,71 +240,43 @@ mod tests {
|
||||
assert!(VuConsoleConfig::try_from(args).is_ok());
|
||||
}
|
||||
|
||||
fn test_backend_start_and_stop(args: ConsoleArgs) {
|
||||
fn test_backend_start_and_stop(args: ConsoleArgs) -> Result<()> {
|
||||
let config = VuConsoleConfig::try_from(args).expect("Wrong config");
|
||||
|
||||
let tcp_addrs = config.generate_tcp_addrs();
|
||||
let backend = config.backend;
|
||||
|
||||
for (_socket, tcp_addr) in config
|
||||
for (socket, tcp_addr) in config
|
||||
.generate_socket_paths()
|
||||
.into_iter()
|
||||
.zip(tcp_addrs.iter())
|
||||
{
|
||||
let controller = ConsoleController::new(backend);
|
||||
let arc_controller = Arc::new(RwLock::new(controller));
|
||||
let vu_console_backend = Arc::new(RwLock::new(
|
||||
VhostUserConsoleBackend::new(arc_controller)
|
||||
.map_err(Error::CouldNotCreateBackend)
|
||||
.expect("Fail create vhuconsole backend"),
|
||||
));
|
||||
|
||||
let mut _daemon = VhostUserDaemon::new(
|
||||
String::from("vhost-device-console-backend"),
|
||||
vu_console_backend.clone(),
|
||||
GuestMemoryAtomic::new(GuestMemoryMmap::new()),
|
||||
)
|
||||
.map_err(Error::CouldNotCreateDaemon)
|
||||
.expect("Failed create daemon");
|
||||
|
||||
// Start the corresponinding console thread
|
||||
let read_handle = if backend == BackendType::Nested {
|
||||
VhostUserConsoleBackend::start_console_thread(&vu_console_backend)
|
||||
} else {
|
||||
VhostUserConsoleBackend::start_tcp_console_thread(
|
||||
&vu_console_backend,
|
||||
tcp_addr.clone(),
|
||||
)
|
||||
};
|
||||
|
||||
// Kill console input thread
|
||||
vu_console_backend.read().unwrap().kill_console_thread();
|
||||
|
||||
// Wait for read thread to exit
|
||||
assert_matches!(read_handle.join(), Ok(_));
|
||||
start_backend_server(socket, tcp_addr.to_string(), backend)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_start_net_backend_success() {
|
||||
fn test_start_backend_server_success() {
|
||||
let args = ConsoleArgs {
|
||||
socket_path: String::from("/tmp/vhost.sock").into(),
|
||||
socket_path: String::from("/not_a_dir/vhost.sock").into(),
|
||||
backend: BackendType::Network,
|
||||
tcp_port: String::from("12345"),
|
||||
socket_count: 1,
|
||||
};
|
||||
|
||||
test_backend_start_and_stop(args);
|
||||
assert!(test_backend_start_and_stop(args).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_start_nested_backend_success() {
|
||||
let args = ConsoleArgs {
|
||||
socket_path: String::from("/tmp/vhost.sock").into(),
|
||||
backend: BackendType::Nested,
|
||||
tcp_port: String::from("12345"),
|
||||
fn test_start_backend_success() {
|
||||
let config = VuConsoleConfig {
|
||||
socket_path: String::from("/not_a_dir/vhost.sock").into(),
|
||||
backend: BackendType::Network,
|
||||
tcp_port: String::from("12346"),
|
||||
socket_count: 1,
|
||||
};
|
||||
|
||||
test_backend_start_and_stop(args);
|
||||
assert!(start_backend(config).is_err());
|
||||
}
|
||||
}
|
||||
|
||||
@ -817,6 +817,7 @@ impl VhostUserBackendMut for VhostUserConsoleBackend {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::io::Cursor;
|
||||
use virtio_bindings::virtio_ring::{VRING_DESC_F_NEXT, VRING_DESC_F_WRITE};
|
||||
use virtio_queue::{mock::MockSplitQueue, Descriptor, Queue};
|
||||
use vm_memory::{Bytes, GuestAddress, GuestMemoryAtomic, GuestMemoryMmap};
|
||||
@ -839,15 +840,12 @@ mod tests {
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
// Artificial memory
|
||||
let mem = GuestMemoryAtomic::new(
|
||||
GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap(),
|
||||
);
|
||||
|
||||
// Update memory
|
||||
vu_console_backend.update_memory(mem.clone()).unwrap();
|
||||
|
||||
// Artificial Vring
|
||||
let vring = VringRwLock::new(mem, 0x1000).unwrap();
|
||||
vring.set_queue_info(0x100, 0x200, 0x300).unwrap();
|
||||
vring.set_queue_ready(true);
|
||||
@ -884,12 +882,10 @@ mod tests {
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
// Artificial memory
|
||||
let mem = GuestMemoryAtomic::new(
|
||||
GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap(),
|
||||
);
|
||||
|
||||
// Artificial Vring
|
||||
let vring = VringRwLock::new(mem.clone(), 0x1000).unwrap();
|
||||
|
||||
// Empty descriptor chain should be ignored
|
||||
@ -945,7 +941,6 @@ mod tests {
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
// Artificial memory
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
|
||||
// Test 1: Empty queue
|
||||
@ -1020,7 +1015,6 @@ mod tests {
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
// Artificial memory
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
|
||||
// Test 1: Empty queue
|
||||
@ -1071,7 +1065,6 @@ mod tests {
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
// Artificial memory & update device's memory
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
let mem_1 = GuestMemoryAtomic::new(mem.clone());
|
||||
vu_console_backend.update_memory(mem_1.clone()).unwrap();
|
||||
@ -1125,7 +1118,6 @@ mod tests {
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
// Artificial memory
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
|
||||
// Test 1: Empty queue
|
||||
@ -1181,7 +1173,6 @@ mod tests {
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
// Artificial memory
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
let desc_chain = build_desc_chain(&mem, 1, vec![0], 0x200);
|
||||
let mem1 = GuestMemoryAtomic::new(mem.clone());
|
||||
@ -1223,7 +1214,6 @@ mod tests {
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
// Artificial memory
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
|
||||
// Test 1: Empty queue
|
||||
@ -1238,7 +1228,8 @@ mod tests {
|
||||
let mem1 = GuestMemoryAtomic::new(mem.clone());
|
||||
let vring = VringRwLock::new(mem1.clone(), 0x1000).unwrap();
|
||||
vu_console_backend.update_memory(mem1).unwrap();
|
||||
assert!(!vu_console_backend
|
||||
|
||||
assert!(vu_console_backend
|
||||
.process_rx_requests(vec![desc_chain], &vring)
|
||||
.unwrap());
|
||||
|
||||
@ -1248,14 +1239,16 @@ mod tests {
|
||||
let vring = VringRwLock::new(mem1.clone(), 0x1000).unwrap();
|
||||
vu_console_backend.update_memory(mem1).unwrap();
|
||||
|
||||
let input_buffer = "Hello!".to_string();
|
||||
let _ = vu_console_backend.rx_data_fifo.add(input_buffer.clone());
|
||||
assert_eq!(
|
||||
vu_console_backend
|
||||
.process_rx_requests(vec![desc_chain], &vring)
|
||||
.unwrap_err(),
|
||||
Error::DescriptorWriteFailed
|
||||
);
|
||||
let input_buffer = b"Hello!";
|
||||
// Add each byte individually to the rx_data_fifo
|
||||
for &byte in input_buffer.clone().iter() {
|
||||
let _ = vu_console_backend.rx_data_fifo.add(byte);
|
||||
}
|
||||
|
||||
// available_data are 0 so min_limit is 0 too
|
||||
assert!(vu_console_backend
|
||||
.process_rx_requests(vec![desc_chain], &vring)
|
||||
.unwrap());
|
||||
|
||||
// Test 4: Fill message to the buffer. Everything should work!
|
||||
let desc_chain = build_desc_chain(&mem, 1, vec![VRING_DESC_F_WRITE as u16], 0x200);
|
||||
@ -1263,8 +1256,10 @@ mod tests {
|
||||
let vring = VringRwLock::new(mem1.clone(), 0x1000).unwrap();
|
||||
vu_console_backend.update_memory(mem1).unwrap();
|
||||
|
||||
let input_buffer = "Hello!".to_string();
|
||||
let _ = vu_console_backend.rx_data_fifo.add(input_buffer.clone());
|
||||
let input_buffer = b"Hello!";
|
||||
for &byte in input_buffer.clone().iter() {
|
||||
let _ = vu_console_backend.rx_data_fifo.add(byte);
|
||||
}
|
||||
assert!(vu_console_backend
|
||||
.process_rx_requests(vec![desc_chain.clone()], &vring)
|
||||
.unwrap());
|
||||
@ -1283,37 +1278,90 @@ mod tests {
|
||||
.copied()
|
||||
.collect();
|
||||
|
||||
assert_eq!(String::from_utf8(read_buffer).unwrap(), input_buffer);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_virtio_console_start_tcp_console_thread() {
|
||||
let console_controller = Arc::new(RwLock::new(ConsoleController::new(BackendType::Nested)));
|
||||
let vu_console_backend = Arc::new(RwLock::new(
|
||||
VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend"),
|
||||
));
|
||||
let tcp_addr = "127.0.0.1:12345".to_string();
|
||||
|
||||
let read_handle = VhostUserConsoleBackend::start_tcp_console_thread(
|
||||
&vu_console_backend,
|
||||
tcp_addr.clone(),
|
||||
);
|
||||
vu_console_backend.read().unwrap().kill_console_thread();
|
||||
assert!(read_handle.join().is_ok());
|
||||
assert_eq!(read_buffer, input_buffer);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_virtio_console_start_nested_console_thread() {
|
||||
let console_controller = Arc::new(RwLock::new(ConsoleController::new(BackendType::Nested)));
|
||||
let vu_console_backend = Arc::new(RwLock::new(
|
||||
VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend"),
|
||||
));
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
let read_handle = VhostUserConsoleBackend::start_console_thread(&vu_console_backend);
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
let mem = GuestMemoryAtomic::new(mem);
|
||||
vu_console_backend.update_memory(mem.clone()).unwrap();
|
||||
let vring = VringRwLock::new(mem, 0x1000).unwrap();
|
||||
|
||||
vu_console_backend.read().unwrap().kill_console_thread();
|
||||
assert!(read_handle.join().is_ok());
|
||||
let input_data = b"H";
|
||||
let cursor = Cursor::new(input_data.clone().to_vec());
|
||||
|
||||
// Replace stdin with a cursor for testing
|
||||
vu_console_backend.stdin = Some(Box::new(cursor));
|
||||
|
||||
vu_console_backend.ready_to_write = true;
|
||||
assert!(vu_console_backend
|
||||
.handle_event(KEY_EFD, EventSet::IN, &[vring], 0)
|
||||
.is_ok());
|
||||
|
||||
let received_byte = vu_console_backend.rx_data_fifo.peek();
|
||||
|
||||
// verify that the character has been received and is the one we sent
|
||||
assert!(received_byte.clone().is_ok());
|
||||
assert_eq!(received_byte.unwrap(), input_data[0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_virtio_console_tcp_console_read_func() {
|
||||
let console_controller =
|
||||
Arc::new(RwLock::new(ConsoleController::new(BackendType::Network)));
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
let mem = GuestMemoryAtomic::new(mem);
|
||||
vu_console_backend.update_memory(mem.clone()).unwrap();
|
||||
let vring = VringRwLock::new(mem, 0x1000).unwrap();
|
||||
|
||||
let input_data = b"H";
|
||||
let cursor = Cursor::new(input_data.clone().to_vec());
|
||||
|
||||
// Replace stream with a cursor for testing
|
||||
vu_console_backend.stream = Some(Box::new(cursor));
|
||||
|
||||
vu_console_backend.ready_to_write = true;
|
||||
assert!(vu_console_backend
|
||||
.handle_event(KEY_EFD, EventSet::IN, &[vring], 0)
|
||||
.is_ok());
|
||||
|
||||
let received_byte = vu_console_backend.rx_data_fifo.peek();
|
||||
|
||||
// verify that the character has been received and is the one we sent
|
||||
assert!(received_byte.clone().is_ok());
|
||||
assert_eq!(received_byte.unwrap(), input_data[0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_virtio_console_tcp_console_write_func() {
|
||||
let console_controller =
|
||||
Arc::new(RwLock::new(ConsoleController::new(BackendType::Network)));
|
||||
let mut vu_console_backend = VhostUserConsoleBackend::new(console_controller)
|
||||
.expect("Failed create vhuconsole backend");
|
||||
|
||||
let mem = GuestMemoryMmap::<()>::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
|
||||
let mem = GuestMemoryAtomic::new(mem);
|
||||
vu_console_backend.update_memory(mem.clone()).unwrap();
|
||||
|
||||
// Test 1: Call the actual read function
|
||||
let cursor = Cursor::new(Vec::new());
|
||||
|
||||
vu_console_backend.stream = Some(Box::new(cursor));
|
||||
vu_console_backend
|
||||
.output_queue
|
||||
.add("Test".to_string())
|
||||
.unwrap();
|
||||
vu_console_backend.write_tcp_stream();
|
||||
|
||||
// All data has been consumed by the cursor
|
||||
assert_eq!(vu_console_backend.output_queue.size(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user