wireshift-fallback 0.1.1

Blocking worker-pool fallback backend for wireshift
Documentation
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)); // Cancelled

    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 } => {
            // bytes should be 8 ("gpu read")
            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"));
}