dd-lib 0.2.1

library functions for a clone of the unix coreutil dd
Documentation
//! integration tests for [dd][dd_lib::dd]

use super::{dd_pipe_err, Success};
use opts::Opts;
use std::{
    fs,
    io::{Read, Write},
    path::Path,
};

use tempfile::{tempdir, TempDir};

const IN_PATH: &str = "in_file.txt";
const OUT_PATH: &str = "out_file.txt";
const BLOCK_SIZE: usize = 1024;
const TOTAL_BLOCKS: usize = 1024;
const TOTAL_BYTES: usize = BLOCK_SIZE * TOTAL_BLOCKS;

#[test]
fn base_case() {
    let dir = tempdir().unwrap();
    let in_path = string_path(&dir, IN_PATH);
    let out_path = string_path(&dir, OUT_PATH);

    write_file(&in_path, &mut [b'a'; TOTAL_BYTES]);
    let args = vec!["dd".to_string(), keyval("if", &in_path), keyval("of", &out_path)];
    let opts = Opts::new(args).unwrap();

    if let Ok(Success::Bytes { bytes, .. }) = dd_pipe_err(&opts, vec![]) {
        assert_eq!(bytes, TOTAL_BYTES)
    } else {
        panic!("expected Ok(Success::Bytes)")
    }
    let output = read_file(out_path);

    assert_eq!(output, vec![b'a'; TOTAL_BYTES]);
}
#[test]
fn conversion_to_uppercase() {
    let dir = tempdir().unwrap();
    let (in_path, out_path) = (string_path(&dir, IN_PATH), string_path(&dir, OUT_PATH));
    write_file(&in_path, &mut [b'a'; 1024 * 1024]);
    let args = vec![
        "dd".to_string(),
        keyval("if", &in_path),
        keyval("of", &out_path),
        keyval("conv", "ucase"),
    ];
    let opts = Opts::new(args).unwrap();
    if let Ok(Success::Bytes { bytes, .. }) = dd_pipe_err(&opts, vec![]) {
        assert_eq!(bytes, 1024 * 1024)
    } else {
        panic!("expected Ok(Success::Bytes)")
    }
    let output = read_file(out_path);

    assert_eq!(output, vec![b'A'; 1024 * 1024]);
}
#[test]
fn seek_input_and_block_size() {
    let dir = tempdir().unwrap();
    let (in_path, out_path) = (string_path(&dir, IN_PATH), string_path(&dir, OUT_PATH));
    write_file(&in_path, &mut [b'a'; 1024 * 1024]);
    let args = vec![
        "dd".to_string(),
        keyval("if", &in_path),
        keyval("of", &out_path),
        keyval("ibs", "1024"),
        keyval("iseek", "1"), // 1 block, not one byte
    ];
    let opts = Opts::new(args).unwrap();

    if let Ok(Success::Bytes { bytes, .. }) = dd_pipe_err(&opts, vec![]) {
        assert_eq!(bytes, 1023 * 1024)
    } else {
        panic!("expected Ok(Success::Bytes)")
    }
    let got = read_file(out_path);

    assert_eq!(got, vec![b'a'; 1023 * 1024]);
}
#[test]
fn block() {
    let dir = tempdir().unwrap();
    let (in_path, out_path) = (string_path(&dir, IN_PATH), string_path(&dir, OUT_PATH));
    let mut input: Vec<u8> = "aaaaa\n\n\n\nbbbb\nccc\ndddddd".bytes().collect();
    write_file(&in_path, &mut input);

    let args = vec![
        "dd".to_string(),
        keyval("if", &in_path),
        keyval("of", &out_path),
        keyval("cbs", "5"), // five bytes;
        keyval("conv", "block"),
    ];

    if let Ok(Success::Block {
        lines,
        truncated,
        padded,
        block_size,
        ..
    }) = dd_pipe_err(&Opts::new(args).unwrap(), vec![])
    {
        assert_eq!((lines, truncated, padded, block_size), (4, 1, 2, 5));
    } else {
        panic!("expected Ok(Success::Bytes)")
    }

    let got = read_file(out_path);
    let want: Vec<u8> = concat!("aaaaa", "bbbb ", "ccc  ", "ddddd").bytes().collect();

    assert_eq!(want, got)
}
fn string_path(dir: &TempDir, file: &str) -> String { dir.path().join(file).to_str().unwrap().to_string() }

fn keyval<S: AsRef<str>>(key: S, val: S) -> String { format!("{}={}", key.as_ref(), val.as_ref()) }

fn write_file<P: AsRef<Path>>(path: P, data: &mut [u8]) {
    let mut f = fs::File::create(path.as_ref()).unwrap();
    f.write_all(data).unwrap();
}

fn read_file<P: AsRef<Path>>(path: P) -> Vec<u8> {
    let mut f = fs::File::open(path).unwrap();
    let mut buf = Vec::new();
    f.read_to_end(&mut buf).unwrap();
    buf
}