ipc-ring48 1.0.1

A bounded 48-byte POSIX shared-memory SPSC queue for Rust.
Documentation
use std::fs;
use std::process::{Command, Output};

fn bin() -> &'static str {
    env!("CARGO_BIN_EXE_ipc-ring48")
}

fn run(args: &[&str]) -> Output {
    Command::new(bin())
        .args(args)
        .output()
        .expect("ipc-ring48 command runs")
}

fn assert_success(args: &[&str]) -> Output {
    let output = run(args);
    assert!(
        output.status.success(),
        "command {:?} failed\nstdout: {}\nstderr: {}",
        args,
        String::from_utf8_lossy(&output.stdout),
        String::from_utf8_lossy(&output.stderr)
    );
    output
}

fn assert_code(args: &[&str], code: i32) -> Output {
    let output = run(args);
    assert_eq!(
        output.status.code(),
        Some(code),
        "command {:?} had unexpected status\nstdout: {}\nstderr: {}",
        args,
        String::from_utf8_lossy(&output.stdout),
        String::from_utf8_lossy(&output.stderr)
    );
    output
}

#[test]
fn cli_exercises_queue_lifecycle_order_full_empty_binary_and_unlink() {
    assert_success(&["unlink"]);
    assert_success(&["unlink"]);
    assert_success(&["init", "4"]);

    assert_success(&["push-u64", "1", "7", "13", "43", "127", "255"]);
    let output = assert_success(&["pop-u64"]);
    assert_eq!(
        String::from_utf8_lossy(&output.stdout).trim(),
        "1 7 13 43 127 255"
    );

    assert_success(&["push-text", "first"]);
    assert_success(&["push-text", "second"]);
    let first = assert_success(&["pop-text"]);
    let second = assert_success(&["pop-text"]);
    assert_eq!(String::from_utf8_lossy(&first.stdout).trim(), "first");
    assert_eq!(String::from_utf8_lossy(&second.stdout).trim(), "second");

    assert_success(&["push-text", "a"]);
    assert_success(&["push-text", "b"]);
    assert_success(&["push-text", "c"]);
    assert_success(&["push-text", "d"]);
    let full = assert_code(&["push-text", "e"], 2);
    assert!(String::from_utf8_lossy(&full.stderr).contains("queue full"));

    assert_success(&["pop-text"]);
    assert_success(&["pop-text"]);
    assert_success(&["pop-text"]);
    assert_success(&["pop-text"]);
    let empty = assert_code(&["pop-text"], 2);
    assert!(String::from_utf8_lossy(&empty.stderr).contains("queue empty"));

    let temp = std::env::temp_dir();
    let input_path = temp.join(format!("ipc-ring48-test-in-{}.bin", std::process::id()));
    let output_path = temp.join(format!("ipc-ring48-test-out-{}.bin", std::process::id()));
    let bytes = (0_u8..48).collect::<Vec<_>>();
    fs::write(&input_path, &bytes).expect("write input fixture");

    assert_success(&["push-file", input_path.to_str().unwrap()]);
    let output = assert_success(&["pop-bin"]);
    fs::write(&output_path, &output.stdout).expect("write output fixture");
    assert_eq!(fs::read(&output_path).unwrap(), bytes);

    let _ = fs::remove_file(input_path);
    let _ = fs::remove_file(output_path);

    assert_success(&["unlink"]);
    assert_success(&["unlink"]);
}