use std::collections::HashMap;
use std::io::Write;
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use tempfile::NamedTempFile;
use wireshift_core::buffer::{Buffer, Submitted};
use wireshift_core::op::CompletionPayload;
use wireshift_core::ops::AlignedBuffer;
use wireshift_fallback::ops::read::{
execute_read, execute_read_fixed, execute_read_gpu, execute_read_vectored,
};
fn setup_file_with_content(content: &[u8]) -> NamedTempFile {
let mut file = NamedTempFile::new().unwrap();
file.write_all(content).unwrap();
file
}
fn create_buffer(size: usize) -> Buffer<Submitted> {
Buffer::<Submitted>::from_vec(vec![0; size]).unwrap()
}
#[test]
fn test_execute_read_success() {
let file = setup_file_with_content(b"hello world");
let buffer = create_buffer(5);
let canceled = Arc::new(AtomicBool::new(false));
let result = execute_read(file.reopen().unwrap(), 0, buffer, canceled, None);
assert!(result.is_ok());
match result.unwrap() {
CompletionPayload::Read {
buffer: completed,
bytes,
} => {
assert_eq!(bytes, 5);
assert_eq!(completed.filled(), b"hello");
}
_ => panic!("Expected Read payload"),
}
}
#[test]
fn test_execute_read_with_offset() {
let file = setup_file_with_content(b"hello world");
let buffer = create_buffer(5);
let canceled = Arc::new(AtomicBool::new(false));
let result = execute_read(file.reopen().unwrap(), 6, buffer, canceled, None);
assert!(result.is_ok());
match result.unwrap() {
CompletionPayload::Read {
buffer: completed,
bytes,
} => {
assert_eq!(bytes, 5);
assert_eq!(completed.filled(), b"world");
}
_ => panic!("Expected Read payload"),
}
}
#[test]
fn test_execute_read_with_len() {
let file = setup_file_with_content(b"hello world");
let buffer = create_buffer(10);
let canceled = Arc::new(AtomicBool::new(false));
let result = execute_read(file.reopen().unwrap(), 0, buffer, canceled, Some(5));
assert!(result.is_ok());
match result.unwrap() {
CompletionPayload::Read {
buffer: completed,
bytes,
} => {
assert_eq!(bytes, 5);
assert_eq!(completed.filled(), b"hello");
}
_ => panic!("Expected Read payload"),
}
}
#[test]
fn test_execute_read_canceled() {
let file = setup_file_with_content(b"hello world");
let buffer = create_buffer(5);
let canceled = Arc::new(AtomicBool::new(true));
let result = execute_read(file.reopen().unwrap(), 0, buffer, canceled, None);
assert!(result.is_err());
let err = result.unwrap_err();
assert!(format!("{:?}", err).contains("Canceled"));
assert!(format!("{:?}", err).contains("read canceled before data transfer started"));
}
#[test]
fn test_execute_read_vectored_success() {
let file = setup_file_with_content(b"hello world");
let buffers = vec![create_buffer(5), create_buffer(5)];
let result = execute_read_vectored(file.reopen().unwrap(), 0, buffers);
assert!(result.is_ok());
match result.unwrap() {
CompletionPayload::ReadVectored {
buffers: completed_buffers,
bytes,
} => {
assert_eq!(bytes, 10);
assert_eq!(completed_buffers.len(), 2);
assert_eq!(completed_buffers[0].filled(), b"hello");
assert_eq!(completed_buffers[1].filled(), b" worl");
}
_ => panic!("Expected ReadVectored payload"),
}
}
#[test]
fn test_execute_read_fixed_success() {
let file = setup_file_with_content(b"hello world");
let mut fixed_files = HashMap::new();
fixed_files.insert(42, file.reopen().unwrap());
let buffer = create_buffer(5);
let canceled = Arc::new(AtomicBool::new(false));
let result = execute_read_fixed(42, 0, buffer, canceled, &mut fixed_files);
assert!(result.is_ok());
match result.unwrap() {
CompletionPayload::Read {
buffer: completed,
bytes,
} => {
assert_eq!(bytes, 5);
assert_eq!(completed.filled(), b"hello");
}
_ => panic!("Expected Read payload"),
}
}
#[test]
fn test_execute_read_fixed_missing_slot() {
let mut fixed_files = HashMap::new();
let buffer = create_buffer(5);
let canceled = Arc::new(AtomicBool::new(false));
let result = execute_read_fixed(99, 0, buffer, canceled, &mut fixed_files);
assert!(result.is_err());
let err = result.unwrap_err();
assert!(format!("{:?}", err).contains("Completion"));
assert!(format!("{:?}", err).contains("direct descriptor slot 99 was read before open"));
}
#[test]
fn test_execute_read_gpu_success() {
let file = setup_file_with_content(b"hello gpu read");
let buffer = AlignedBuffer::new(5).unwrap();
let canceled = Arc::new(AtomicBool::new(false));
let result = execute_read_gpu(file.reopen().unwrap(), 6, buffer, canceled);
assert!(result.is_ok());
match result.unwrap() {
CompletionPayload::GpuRead { mut buffer, bytes } => {
assert_eq!(bytes, 8);
assert_eq!(&buffer.as_mut_slice()[..bytes], b"gpu read");
}
_ => panic!("Expected GpuRead payload"),
}
}
#[test]
fn test_execute_read_gpu_canceled() {
let file = setup_file_with_content(b"hello gpu read");
let buffer = AlignedBuffer::new(5).unwrap();
let canceled = Arc::new(AtomicBool::new(true));
let result = execute_read_gpu(file.reopen().unwrap(), 6, buffer, canceled);
assert!(result.is_err());
let err = result.unwrap_err();
assert!(format!("{:?}", err).contains("Canceled"));
assert!(format!("{:?}", err).contains("gpu staged read canceled before data transfer started"));
}