wireshift-uring 0.1.1

Native Linux io_uring backend for wireshift
Documentation
#![allow(missing_docs)]

use std::fs::File;
use std::os::fd::AsRawFd;
use wireshift_core::backend::{Backend, BackendSubmission, CancellationHandle};
use wireshift_core::buffer::BufferPool;
use wireshift_core::config::{RegisteredBufferConfig, RingConfig};
use wireshift_core::op::OpDescriptor;
use wireshift_uring::UringBackend;

#[test]
fn test_unit_new_default_config() {
    let (tx, _rx) = std::sync::mpsc::channel();
    let config = RingConfig::default();
    let backend = UringBackend::new(&config, tx).expect("backend creation should succeed");
    assert_eq!(
        backend.kind(),
        wireshift_core::backend::BackendKind::IoUring
    );
}

#[test]
fn test_unit_new_with_sq_poll() {
    let (tx, _rx) = std::sync::mpsc::channel();
    let config = RingConfig {
        sq_poll_idle_ms: Some(100),
        ..RingConfig::default()
    };
    let backend = UringBackend::new(&config, tx).expect("backend creation should succeed");
    assert_eq!(
        backend.kind(),
        wireshift_core::backend::BackendKind::IoUring
    );
}

#[test]
fn test_unit_new_invalid_registered_buffers() {
    let (tx, _rx) = std::sync::mpsc::channel();
    let config = RingConfig {
        registered_buffers: Some(RegisteredBufferConfig {
            count: usize::MAX as u32,
            size: 4096,
        }),
        ..RingConfig::default()
    };
    let result = UringBackend::new(&config, tx);
    assert!(
        result.is_err(),
        "should fail on impossibly huge registration size"
    );
}

#[test]
fn test_unit_register_unregister_files() {
    let (tx, _rx) = std::sync::mpsc::channel();
    let config = RingConfig::default();
    let backend = UringBackend::new(&config, tx).expect("backend creation");

    let _ = backend.unregister_files(); // unregister sparse first
    let file = File::open("/dev/null").expect("open /dev/null");
    backend
        .register_files(&[file.as_raw_fd()])
        .expect("register files");
    backend.unregister_files().expect("unregister files");
}

#[test]
fn test_unit_supports_native_read() {
    let (tx, _rx) = std::sync::mpsc::channel();
    let config = RingConfig::default();
    let backend = UringBackend::new(&config, tx).expect("backend creation");

    let file = File::open("/dev/null").expect("open /dev/null");
    let buffer = BufferPool::new(4096, 1)
        .unwrap()
        .acquire()
        .unwrap()
        .into_submitted();
    let desc = OpDescriptor::Read {
        file,
        offset: 0,
        buffer,
        len: None,
    };

    assert!(
        backend.supports_native(&desc),
        "Read should be supported natively"
    );
}

#[test]
fn test_unit_submit_and_cancel() {
    let (tx, _rx) = std::sync::mpsc::channel();
    let config = RingConfig::default();
    let backend = UringBackend::new(&config, tx).expect("backend creation");

    let file = File::open("/dev/null").expect("open /dev/null");
    let buffer = BufferPool::new(4096, 1)
        .unwrap()
        .acquire()
        .unwrap()
        .into_submitted();
    let descriptor = OpDescriptor::Read {
        file,
        offset: 0,
        buffer,
        len: None,
    };

    let submission = BackendSubmission { timeout: None,  id: 1, descriptor };

    backend.submit(submission).expect("submit");

    let cancellation = CancellationHandle { target: 1 };
    backend.cancel(cancellation).expect("cancel");
}

#[test]
fn test_unit_shutdown() {
    let (tx, _rx) = std::sync::mpsc::channel();
    let config = RingConfig::default();
    let backend = UringBackend::new(&config, tx).expect("backend creation");
    backend.shutdown().expect("shutdown should succeed");

    // Test that sending after shutdown fails
    let file = File::open("/dev/null").expect("open /dev/null");
    let buffer = BufferPool::new(4096, 1)
        .unwrap()
        .acquire()
        .unwrap()
        .into_submitted();
    let descriptor = OpDescriptor::Read {
        file,
        offset: 0,
        buffer,
        len: None,
    };
    let submission = BackendSubmission { timeout: None,  id: 2, descriptor };
    let result = backend.submit(submission);
    assert!(
        result.is_err(),
        "submit after shutdown should return an error"
    );
}