icydb-cli 0.296.9

Developer CLI tools for IcyDB
use std::{
    fs,
    os::unix::fs::PermissionsExt as _,
    panic::{AssertUnwindSafe, catch_unwind},
    path::PathBuf,
    process::Command,
};

use super::{IcpCallKind, call_hex, probe_output};

#[test]
fn private_argument_file_lives_through_child_and_is_removed_on_success() {
    let bytes = [0, 255, 1, 0, 128];
    let mut argument_path = PathBuf::new();
    let result = call_hex(
        &bytes,
        |path| {
            argument_path = path.to_owned();
            assert_eq!(fs::read(path).unwrap(), bytes);
            assert_eq!(
                fs::metadata(path).unwrap().permissions().mode() & 0o777,
                0o600
            );
            let mut command = Command::new("sh");
            command.args(["-c", "test -f \"$1\" && printf 00", "argument-file"]);
            command.arg(path);
            command
        },
        str::to_owned,
        IcpCallKind::Query,
        probe_output,
    );
    assert_eq!(result.unwrap(), [0]);
    assert!(!argument_path.exists());
}

#[test]
fn argument_file_is_removed_after_child_and_response_failures() {
    for recipe in [
        Some("exit 7"),
        Some("printf invalid_hex"),
        Some("printf '\\377'"),
        None,
    ] {
        let mut argument_path = PathBuf::new();
        let result = call_hex(
            b"request",
            |path| {
                argument_path = path.to_owned();
                assert_eq!(fs::read(path).unwrap(), b"request");
                if let Some(recipe) = recipe {
                    let mut command = Command::new("sh");
                    command.args(["-c", recipe]);
                    command
                } else {
                    Command::new(path.with_extension("missing-executable"))
                }
            },
            str::to_owned,
            IcpCallKind::Query,
            probe_output,
        );
        assert!(result.is_err());
        assert!(!argument_path.exists());
    }
}

#[test]
fn argument_file_is_removed_during_unwind() {
    let mut argument_path = PathBuf::new();
    let panic = catch_unwind(AssertUnwindSafe(|| {
        let _ = call_hex(
            b"request",
            |path| {
                argument_path = path.to_owned();
                panic!("command construction failed")
            },
            str::to_owned,
            IcpCallKind::Query,
            probe_output,
        );
    }));
    assert!(panic.is_err());
    assert!(!argument_path.exists());
}