mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 11:37:44 +00:00
Builds out arg parsing. Adds support for if, of, & multiplier strings)
- Adds support for calling dd fn from cl - Adds basic cl tests from project root - Adds support for multiplier strings (c, w, b, kB, KB, KiB, ... EB, E, EiB.
This commit is contained in:
parent
0df457596c
commit
4996308753
6 changed files with 891 additions and 341 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1593,6 +1593,7 @@ dependencies = [
|
|||
name = "uu_dd"
|
||||
version = "0.0.4"
|
||||
dependencies = [
|
||||
"getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hex-literal 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"md-5 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -17,6 +17,8 @@ path = "src/dd.rs"
|
|||
[dependencies]
|
||||
uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
|
||||
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
|
||||
# Probably best to keep this identical to the version of getopts in the uucore crate
|
||||
getopts = "<= 0.2.21"
|
||||
|
||||
[dev-dependencies]
|
||||
md-5 = "0.9"
|
||||
|
|
|
@ -10,28 +10,35 @@
|
|||
#[macro_use]
|
||||
extern crate uucore;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_dd_internal;
|
||||
|
||||
mod ddargs;
|
||||
|
||||
use std::error::Error;
|
||||
use std::fs::File;
|
||||
use std::io::{
|
||||
self, Read, Write,
|
||||
BufWriter,
|
||||
};
|
||||
use std::sync::mpsc;
|
||||
use std::thread;
|
||||
use getopts;
|
||||
|
||||
const NAME: &str = "dd";
|
||||
const SUMMARY: &str = "Copies, and optionally converts, file system resources.";
|
||||
const SUMMARY: &str = "convert and copy a file";
|
||||
const LONG_HELP: &str = "TODO: This is where the long help string for dd goes!";
|
||||
|
||||
const RTN_SUCCESS: i32 = 0;
|
||||
const RTN_FAILURE: i32 = 1;
|
||||
|
||||
// ----- Conversion -----
|
||||
//
|
||||
// Conversion tables are just lookup tables.
|
||||
// eg. The ASCII->EBCDIC table stores the EBCDIC code at the index
|
||||
// obtained by treating the ASCII representation as a number.
|
||||
type ConversionTable = [u8; 256];
|
||||
|
||||
const ascii_to_ebcdic: ConversionTable = [
|
||||
const ASCII_TO_EBCDIC: ConversionTable = [
|
||||
0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
|
||||
|
@ -50,7 +57,7 @@ const ascii_to_ebcdic: ConversionTable = [
|
|||
0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
||||
];
|
||||
|
||||
const ascii_to_ibm: ConversionTable = [
|
||||
const ASCII_TO_IBM: ConversionTable = [
|
||||
0x00, 0x01, 0x02, 0x03, 0x37, 0x2d, 0x2e, 0x2f, 0x16, 0x05, 0x25, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61,
|
||||
|
@ -69,7 +76,7 @@ const ascii_to_ibm: ConversionTable = [
|
|||
0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
||||
];
|
||||
|
||||
const ebcdic_to_ascii: ConversionTable = [
|
||||
const EBCDIC_TO_ASCII: ConversionTable = [
|
||||
0x00, 0x01, 0x02, 0x03, 0x9c, 0x09, 0x86, 0x7f, 0x97, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x9d, 0x85, 0x08, 0x87, 0x18, 0x19, 0x92, 0x8f, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x0a, 0x17, 0x1b, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07,
|
||||
|
@ -88,7 +95,7 @@ const ebcdic_to_ascii: ConversionTable = [
|
|||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
||||
];
|
||||
|
||||
const lcase_to_ucase: ConversionTable = [
|
||||
const LCASE_TO_UCASE: ConversionTable = [
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
|
@ -108,7 +115,7 @@ const lcase_to_ucase: ConversionTable = [
|
|||
|
||||
];
|
||||
|
||||
const ucase_to_lcase: ConversionTable = [
|
||||
const UCASE_TO_LCASE: ConversionTable = [
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
|
@ -127,13 +134,29 @@ const ucase_to_lcase: ConversionTable = [
|
|||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
||||
];
|
||||
|
||||
// ----- Datatypes -----
|
||||
// ----- Types -----
|
||||
enum SrcStat
|
||||
{
|
||||
Read(usize),
|
||||
EOF,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum InternalError
|
||||
{
|
||||
WrongInputType,
|
||||
WrongOutputType,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for InternalError
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Internal dd error")
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for InternalError {}
|
||||
|
||||
struct Input<R: Read>
|
||||
{
|
||||
src: R,
|
||||
|
@ -149,6 +172,47 @@ impl<R: Read> Read for Input<R>
|
|||
}
|
||||
}
|
||||
|
||||
impl Input<io::Stdin>
|
||||
{
|
||||
fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>>
|
||||
{
|
||||
let ibs: usize = ddargs::parse_ibs(matches)?;
|
||||
let output_progress = ddargs::parse_progress_level(matches)?;
|
||||
|
||||
Ok(
|
||||
Input {
|
||||
src: io::stdin(),
|
||||
ibs,
|
||||
output_progress,
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
impl Input<File>
|
||||
{
|
||||
fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>>
|
||||
{
|
||||
let ibs: usize = ddargs::parse_ibs(matches)?;
|
||||
let output_progress = ddargs::parse_progress_level(matches)?;
|
||||
|
||||
if let Some(fname) = matches.opt_str("if")
|
||||
{
|
||||
Ok(Input {
|
||||
src: File::open(fname)?,
|
||||
ibs,
|
||||
output_progress,
|
||||
})
|
||||
}
|
||||
else
|
||||
{
|
||||
Err(Box::new(InternalError::WrongInputType))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Read> Input<R>
|
||||
{
|
||||
fn fill_n(&mut self, buf: &mut [u8], obs: usize) -> Result<SrcStat, Box<dyn Error>>
|
||||
|
@ -182,6 +246,43 @@ struct Output<W: Write>
|
|||
conv_table: Option<ConversionTable>,
|
||||
}
|
||||
|
||||
impl Output<io::Stdout> {
|
||||
fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>>
|
||||
{
|
||||
let obs: usize = ddargs::parse_obs(matches)?;
|
||||
let conv_table = ddargs::parse_conv_table(matches)?;
|
||||
|
||||
Ok(
|
||||
Output {
|
||||
dst: io::stdout(),
|
||||
obs,
|
||||
conv_table,
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Output<File> {
|
||||
fn new(matches: &getopts::Matches) -> Result<Self, Box<dyn Error>>
|
||||
{
|
||||
let obs: usize = ddargs::parse_obs(matches)?;
|
||||
let conv_table = ddargs::parse_conv_table(matches)?;
|
||||
|
||||
if let Some(fname) = matches.opt_str("if")
|
||||
{
|
||||
Ok(Output {
|
||||
dst: File::open(fname)?,
|
||||
obs,
|
||||
conv_table,
|
||||
})
|
||||
}
|
||||
else
|
||||
{
|
||||
Err(Box::new(InternalError::WrongOutputType))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Write> Write for Output<W>
|
||||
{
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize>
|
||||
|
@ -209,10 +310,9 @@ impl<W: Write> Write for Output<W>
|
|||
}
|
||||
}
|
||||
|
||||
// ----- Implementation -----
|
||||
fn gen_prog_updater(rx: mpsc::Receiver<usize>) -> impl Fn() -> ()
|
||||
{
|
||||
move || { // LAAAAMBDA!
|
||||
move || {
|
||||
|
||||
// TODO: Replace ?? with accurate info
|
||||
print!("\rProgress ({}/??)", 0);
|
||||
|
@ -246,7 +346,6 @@ fn dd<R: Read, W: Write>(mut i: Input<R>, mut o: Output<W>) -> Result<(usize, us
|
|||
None
|
||||
};
|
||||
|
||||
|
||||
let mut bytes_in = 0;
|
||||
let mut bytes_out = 0;
|
||||
|
||||
|
@ -278,38 +377,106 @@ fn dd<R: Read, W: Write>(mut i: Input<R>, mut o: Output<W>) -> Result<(usize, us
|
|||
Ok((bytes_in, bytes_out))
|
||||
}
|
||||
|
||||
fn append_dashes_if_not_present(mut acc: Vec<String>, s: &String) -> Vec<String>
|
||||
{
|
||||
if Some("--") == s.get(0..=1) {
|
||||
acc
|
||||
} else {
|
||||
acc.push(format!("--{}", s));
|
||||
acc
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uumain(args: impl uucore::Args) -> i32
|
||||
{
|
||||
// TODO: parse args
|
||||
let dashed_args = args.collect_str()
|
||||
.iter()
|
||||
.fold(Vec::new(), append_dashes_if_not_present);
|
||||
|
||||
let if_name = "foo.txt";
|
||||
let of_name = "bar.txt";
|
||||
let ibs = 512;
|
||||
let obs = 4096;
|
||||
let syntax = format!(
|
||||
"{0} [OPERAND]...\n{0} OPTION",
|
||||
NAME
|
||||
);
|
||||
|
||||
let in_f = File::open(if_name)
|
||||
.expect("TODO: Handle this error in the project-specific way");
|
||||
let matches = app!(&syntax, SUMMARY, LONG_HELP)
|
||||
.optopt(
|
||||
"",
|
||||
"if",
|
||||
"The input file",
|
||||
"FILE"
|
||||
)
|
||||
.optopt(
|
||||
"",
|
||||
"ibs",
|
||||
"read up to BYTES bytes at a time (default: 512)",
|
||||
"BYTES"
|
||||
)
|
||||
.optopt(
|
||||
"",
|
||||
"of",
|
||||
"The output file",
|
||||
"FILE"
|
||||
)
|
||||
.optopt(
|
||||
"",
|
||||
"obs",
|
||||
"write BYTES bytes at a time (default: 512)",
|
||||
"BYTES"
|
||||
)
|
||||
.optopt(
|
||||
"",
|
||||
"conv",
|
||||
"One or more conversion options as a comma-serparated list",
|
||||
"OPT[,OPT]..."
|
||||
)
|
||||
.parse(dashed_args);
|
||||
|
||||
let out_f = File::open(of_name)
|
||||
.expect("TODO: Handle this error in the project-specific way");
|
||||
let out_f = BufWriter::with_capacity(obs, out_f);
|
||||
let result = match (matches.opt_present("if"), matches.opt_present("of"))
|
||||
{
|
||||
(true, true) =>
|
||||
{
|
||||
let i = Input::<File>::new(&matches)
|
||||
.expect("TODO: Return correct error code");
|
||||
let o = Output::<File>::new(&matches)
|
||||
.expect("TODO: Return correct error code");
|
||||
|
||||
let i = Input {
|
||||
src: in_f,
|
||||
ibs,
|
||||
output_progress: false,
|
||||
};
|
||||
let o = Output {
|
||||
dst: out_f,
|
||||
obs,
|
||||
conv_table: None,
|
||||
dd(i, o)
|
||||
},
|
||||
(true, false) =>
|
||||
{
|
||||
let i = Input::<File>::new(&matches)
|
||||
.expect("TODO: Return correct error code");
|
||||
let o = Output::<io::Stdout>::new(&matches)
|
||||
.expect("TODO: Return correct error code");
|
||||
|
||||
dd(i, o)
|
||||
},
|
||||
(false, true) =>
|
||||
{
|
||||
let i = Input::<io::Stdin>::new(&matches)
|
||||
.expect("TODO: Return correct error code");
|
||||
let o = Output::<File>::new(&matches)
|
||||
.expect("TODO: Return correct error code");
|
||||
|
||||
dd(i, o)
|
||||
},
|
||||
(false, false) =>
|
||||
{
|
||||
let i = Input::<io::Stdin>::new(&matches)
|
||||
.expect("TODO: Return correct error code");
|
||||
let o = Output::<io::Stdout>::new(&matches)
|
||||
.expect("TODO: Return correct error code");
|
||||
|
||||
dd(i, o)
|
||||
},
|
||||
};
|
||||
|
||||
match dd(i, o) {
|
||||
match result
|
||||
{
|
||||
Ok((b_in, b_out)) =>
|
||||
{
|
||||
println!("Completed: Bytes in: {}, Bytes out: {}", b_in, b_out);
|
||||
|
||||
// TODO: Print output stats, unless noxfer
|
||||
|
||||
RTN_SUCCESS
|
||||
},
|
||||
Err(_) =>
|
||||
|
@ -317,309 +484,3 @@ pub fn uumain(args: impl uucore::Args) -> i32
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_dd_internal
|
||||
{
|
||||
#[allow(unused_imports)]
|
||||
use super::*;
|
||||
|
||||
use std::io::prelude::*;
|
||||
use std::io::BufReader;
|
||||
use std::fs;
|
||||
use md5::{ Md5, Digest, };
|
||||
use hex_literal::hex;
|
||||
|
||||
macro_rules! make_hash_test (
|
||||
( $test_id:ident, $test_name:expr, $src:expr, $exp:expr ) =>
|
||||
{
|
||||
#[test]
|
||||
fn $test_id()
|
||||
{
|
||||
let tmp_fname = format!("./test-resources/FAILED-{}.test", $test_name);
|
||||
|
||||
let i = Input {
|
||||
src: $src,
|
||||
ibs: 256,
|
||||
output_progress: false,
|
||||
};
|
||||
|
||||
let o = Output {
|
||||
dst: File::create(&tmp_fname).unwrap(),
|
||||
obs: 1024,
|
||||
conv_table: None,
|
||||
};
|
||||
|
||||
dd(i,o).unwrap();
|
||||
|
||||
let res = {
|
||||
let res = File::open(&tmp_fname).unwrap();
|
||||
let res = BufReader::new(res);
|
||||
|
||||
let mut h = Md5::new();
|
||||
for b in res.bytes()
|
||||
{
|
||||
h.update([b.unwrap()]);
|
||||
}
|
||||
|
||||
h.finalize()
|
||||
};
|
||||
|
||||
assert_eq!(hex!($exp), res[..]);
|
||||
|
||||
fs::remove_file(&tmp_fname).unwrap();
|
||||
}
|
||||
};
|
||||
( $test_id:ident, $test_name:expr, $i:expr, $o:expr, $exp:expr ) =>
|
||||
{
|
||||
#[test]
|
||||
fn $test_id()
|
||||
{
|
||||
let tmp_fname = format!("./test-resources/FAILED-{}.test", $test_name);
|
||||
|
||||
let o = Output {
|
||||
dst: File::create(&tmp_fname).unwrap(),
|
||||
obs: $o.obs,
|
||||
conv_table: $o.conv_table,
|
||||
};
|
||||
|
||||
dd($i,o).unwrap();
|
||||
|
||||
let res = {
|
||||
let res = File::open(&tmp_fname).unwrap();
|
||||
let res = BufReader::new(res);
|
||||
|
||||
let mut h = Md5::new();
|
||||
for b in res.bytes()
|
||||
{
|
||||
h.update([b.unwrap()]);
|
||||
}
|
||||
|
||||
h.finalize()
|
||||
};
|
||||
|
||||
assert_eq!(hex!($exp), res[..]);
|
||||
|
||||
fs::remove_file(&tmp_fname).unwrap();
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
macro_rules! make_spec_test (
|
||||
( $test_id:ident, $test_name:expr, $i:expr, $o:expr, $spec:expr ) =>
|
||||
{
|
||||
#[test]
|
||||
fn $test_id()
|
||||
{
|
||||
let tmp_fname = format!("./test-resources/FAILED-{}.test", $test_name);
|
||||
|
||||
let o = Output {
|
||||
dst: File::create(&tmp_fname).unwrap(),
|
||||
obs: $o.obs,
|
||||
conv_table: $o.conv_table,
|
||||
};
|
||||
|
||||
dd($i,o).unwrap();
|
||||
|
||||
let res = File::open(&tmp_fname).unwrap();
|
||||
let res = BufReader::new(res);
|
||||
|
||||
let spec = BufReader::new($spec);
|
||||
|
||||
for (b_res, b_spec) in res.bytes().zip(spec.bytes())
|
||||
{
|
||||
assert_eq!(b_res.unwrap(),
|
||||
b_spec.unwrap());
|
||||
}
|
||||
|
||||
fs::remove_file(&tmp_fname).unwrap();
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
make_hash_test!(
|
||||
empty_file_test,
|
||||
"stdio-empty-file",
|
||||
io::empty(),
|
||||
"d41d8cd98f00b204e9800998ecf8427e"
|
||||
);
|
||||
|
||||
make_hash_test!(
|
||||
zeros_4k_test,
|
||||
"zeros-4k",
|
||||
File::open("./test-resources/zeros-620f0b67a91f7f74151bc5be745b7110.test").unwrap(),
|
||||
"620f0b67a91f7f74151bc5be745b7110"
|
||||
);
|
||||
|
||||
make_hash_test!(
|
||||
ones_4k_test,
|
||||
"ones-4k",
|
||||
File::open("./test-resources/ones-6ae59e64850377ee5470c854761551ea.test").unwrap(),
|
||||
"6ae59e64850377ee5470c854761551ea"
|
||||
);
|
||||
|
||||
make_hash_test!(
|
||||
deadbeef_32k_test,
|
||||
"deadbeef-32k",
|
||||
File::open("./test-resources/deadbeef-18d99661a1de1fc9af21b0ec2cd67ba3.test").unwrap(),
|
||||
"18d99661a1de1fc9af21b0ec2cd67ba3"
|
||||
);
|
||||
|
||||
make_hash_test!(
|
||||
random_73k_test,
|
||||
"random-73k",
|
||||
File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap(),
|
||||
"5828891cb1230748e146f34223bbd3b5"
|
||||
);
|
||||
|
||||
make_spec_test!(
|
||||
atoe_conv_spec_test,
|
||||
"atoe-conv-spec-test",
|
||||
Input {
|
||||
src: File::open("./test-resources/seq-byte-values-b632a992d3aed5d8d1a59cc5a5a455ba.test").unwrap(),
|
||||
ibs: 512,
|
||||
output_progress: false,
|
||||
},
|
||||
Output {
|
||||
dst: Vec::new(), // unused!
|
||||
obs: 512,
|
||||
conv_table: Some(ascii_to_ebcdic),
|
||||
},
|
||||
File::open("./test-resources/gnudd-conv-atoe-seq-byte-values.spec").unwrap()
|
||||
);
|
||||
|
||||
make_spec_test!(
|
||||
etoa_conv_spec_test,
|
||||
"etoa-conv-spec-test",
|
||||
Input {
|
||||
src: File::open("./test-resources/seq-byte-values-b632a992d3aed5d8d1a59cc5a5a455ba.test").unwrap(),
|
||||
ibs: 512,
|
||||
output_progress: false,
|
||||
},
|
||||
Output {
|
||||
dst: Vec::new(), // unused!
|
||||
obs: 512,
|
||||
conv_table: Some(ebcdic_to_ascii),
|
||||
},
|
||||
File::open("./test-resources/gnudd-conv-etoa-seq-byte-values.spec").unwrap()
|
||||
);
|
||||
|
||||
make_spec_test!(
|
||||
atoibm_conv_spec_test,
|
||||
"atoibm-conv-spec-test",
|
||||
Input {
|
||||
src: File::open("./test-resources/seq-byte-values-b632a992d3aed5d8d1a59cc5a5a455ba.test").unwrap(),
|
||||
ibs: 512,
|
||||
output_progress: false,
|
||||
},
|
||||
Output {
|
||||
dst: Vec::new(), // unused!
|
||||
obs: 512,
|
||||
conv_table: Some(ascii_to_ibm),
|
||||
},
|
||||
File::open("./test-resources/gnudd-conv-atoibm-seq-byte-values.spec").unwrap()
|
||||
);
|
||||
|
||||
make_spec_test!(
|
||||
lcase_ascii_to_ucase_ascii,
|
||||
"lcase_ascii_to_ucase_ascii",
|
||||
Input {
|
||||
src: File::open("./test-resources/lcase-ascii.test").unwrap(),
|
||||
ibs: 512,
|
||||
output_progress: false,
|
||||
},
|
||||
Output {
|
||||
dst: Vec::new(), // unused!
|
||||
obs: 512,
|
||||
conv_table: Some(lcase_to_ucase),
|
||||
},
|
||||
File::open("./test-resources/ucase-ascii.test").unwrap()
|
||||
);
|
||||
|
||||
make_spec_test!(
|
||||
ucase_ascii_to_lcase_ascii,
|
||||
"ucase_ascii_to_lcase_ascii",
|
||||
Input {
|
||||
src: File::open("./test-resources/ucase-ascii.test").unwrap(),
|
||||
ibs: 512,
|
||||
output_progress: false,
|
||||
},
|
||||
Output {
|
||||
dst: Vec::new(), // unused!
|
||||
obs: 512,
|
||||
conv_table: Some(ucase_to_lcase),
|
||||
},
|
||||
File::open("./test-resources/lcase-ascii.test").unwrap()
|
||||
);
|
||||
|
||||
#[test]
|
||||
fn all_valid_ascii_ebcdic_ascii_roundtrip_conv_test()
|
||||
{
|
||||
// ASCII->EBCDIC
|
||||
let test_name = "all-valid-ascii-to-ebcdic";
|
||||
let tmp_fname_ae = format!("./test-resources/FAILED-{}.test", test_name);
|
||||
|
||||
let i = Input {
|
||||
src: File::open("./test-resources/all-valid-ascii-chars-37eff01866ba3f538421b30b7cbefcac.test").unwrap(),
|
||||
ibs: 256,
|
||||
output_progress: false,
|
||||
};
|
||||
|
||||
let o = Output {
|
||||
dst: File::create(&tmp_fname_ae).unwrap(),
|
||||
obs: 1024,
|
||||
conv_table: Some(ascii_to_ebcdic),
|
||||
};
|
||||
|
||||
dd(i,o).unwrap();
|
||||
|
||||
// EBCDIC->ASCII
|
||||
let test_name = "all-valid-ebcdic-to-ascii";
|
||||
let tmp_fname_ea = format!("./test-resources/FAILED-{}.test", test_name);
|
||||
|
||||
let i = Input {
|
||||
src: File::open(&tmp_fname_ae).unwrap(),
|
||||
ibs: 256,
|
||||
output_progress: false,
|
||||
};
|
||||
|
||||
let o = Output {
|
||||
dst: File::create(&tmp_fname_ea).unwrap(),
|
||||
obs: 1024,
|
||||
conv_table: Some(ebcdic_to_ascii),
|
||||
};
|
||||
|
||||
dd(i,o).unwrap();
|
||||
|
||||
let res = {
|
||||
let res = File::open(&tmp_fname_ea).unwrap();
|
||||
let res = BufReader::new(res);
|
||||
|
||||
let mut h = Md5::new();
|
||||
for b in res.bytes()
|
||||
{
|
||||
h.update([b.unwrap()]);
|
||||
}
|
||||
|
||||
h.finalize()
|
||||
};
|
||||
|
||||
assert_eq!(hex!("37eff01866ba3f538421b30b7cbefcac"), res[..]);
|
||||
|
||||
fs::remove_file(&tmp_fname_ae).unwrap();
|
||||
fs::remove_file(&tmp_fname_ea).unwrap();
|
||||
}
|
||||
|
||||
//use rand::prelude::*;
|
||||
//#[test]
|
||||
//fn make_test_data()
|
||||
//{
|
||||
// let mut f = File::create("./test-resources/random-walk-through-the-ascii-ranged-forest.test").unwrap();
|
||||
// // let mut rng = rand::thread_rng();
|
||||
|
||||
// for _ in 0..65536 {
|
||||
// f.write(&[c]).unwrap();
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
|
|
303
src/uu/dd/src/ddargs.rs
Normal file
303
src/uu/dd/src/ddargs.rs
Normal file
|
@ -0,0 +1,303 @@
|
|||
use super::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ParseError
|
||||
{
|
||||
MultiplierString(String),
|
||||
MultiplierStringWouldOverflow(String),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ParseError
|
||||
{
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "dd-args: Parse Error")
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ParseError {}
|
||||
|
||||
fn parse_multiplier<'a>(s: &'a str) -> Result<usize, Box<dyn Error>>
|
||||
{
|
||||
let s = s.trim();
|
||||
|
||||
match s
|
||||
{
|
||||
"c" =>
|
||||
Ok(1),
|
||||
"w" =>
|
||||
Ok(2),
|
||||
"b" =>
|
||||
Ok(512),
|
||||
"kB" =>
|
||||
Ok(1000),
|
||||
"K" | "KiB" =>
|
||||
Ok(1024),
|
||||
"MB" =>
|
||||
Ok(1000*1000),
|
||||
"M" | "MiB" =>
|
||||
Ok(1024*1024),
|
||||
"GB" =>
|
||||
Ok(1000*1000*1000),
|
||||
"G" | "GiB" =>
|
||||
Ok(1024*1024*1024),
|
||||
"TB" =>
|
||||
Ok(1000*1000*1000*1000),
|
||||
"T" | "TiB" =>
|
||||
Ok(1024*1024*1024*1024),
|
||||
"PB" =>
|
||||
Ok(1000*1000*1000*1000*1000),
|
||||
"P" | "PiB" =>
|
||||
Ok(1024*1024*1024*1024*1024),
|
||||
"EB" =>
|
||||
Ok(1000*1000*1000*1000*1000*1000),
|
||||
"E" | "EiB" =>
|
||||
Ok(1024*1024*1024*1024*1024*1024),
|
||||
// The following would overflow on my x64 system
|
||||
// "ZB" =>
|
||||
// Ok(1000*1000*1000*1000*1000*1000*1000),
|
||||
// "Z" | "ZiB" =>
|
||||
// Ok(1024*1024*1024*1024*1024*1024*1024),
|
||||
// "YB" =>
|
||||
// Ok(1000*1000*1000*1000*1000*1000*1000*1000),
|
||||
// "Y" | "YiB" =>
|
||||
// Ok(1024*1024*1024*1024*1024*1024*1024*1024),
|
||||
_ =>
|
||||
Err(Box::new(ParseError::MultiplierString(String::from(s)))),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_bytes_with_opt_multiplier(s: String) -> Result<usize, Box<dyn Error>>
|
||||
{
|
||||
if let Some(idx) = s.find(' ')
|
||||
{
|
||||
let base: usize = s[0..idx].parse()?;
|
||||
let mult = parse_multiplier(&s[idx..])?;
|
||||
|
||||
if let Some(bytes) = base.checked_mul(mult)
|
||||
{
|
||||
Ok(bytes)
|
||||
}
|
||||
else
|
||||
{
|
||||
Err(Box::new(ParseError::MultiplierStringWouldOverflow(s)))
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
let bytes: usize = s.parse()?;
|
||||
|
||||
Ok(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_ibs(matches: &getopts::Matches) -> Result<usize, Box<dyn Error>>
|
||||
{
|
||||
if let Some(mixed_str) = matches.opt_str("bs")
|
||||
{
|
||||
parse_bytes_with_opt_multiplier(mixed_str)
|
||||
}
|
||||
else if let Some(mixed_str) = matches.opt_str("ibs")
|
||||
{
|
||||
parse_bytes_with_opt_multiplier(mixed_str)
|
||||
}
|
||||
else
|
||||
{
|
||||
Ok(512)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_progress_level(matches: &getopts::Matches) -> Result<bool, Box<dyn Error>>
|
||||
{
|
||||
// TODO: Implement this stub proc
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
pub fn parse_obs(matches: &getopts::Matches) -> Result<usize, Box<dyn Error>>
|
||||
{
|
||||
if let Some(str_with_prefixes) = matches.opt_str("bs")
|
||||
{
|
||||
// TODO: Parse a string containing the number with potential k, kB, kiB, ... multiplier
|
||||
// possibly implemented elsewhere, but probably not in exactly the dd style
|
||||
panic!()
|
||||
}
|
||||
else if let Some(str_with_prefixes) = matches.opt_str("obs")
|
||||
{
|
||||
// TODO: Parse a string containing the number with potential k, kB, kiB, ... multiplier
|
||||
// possibly implemented elsewhere, but probably not in exactly the dd style
|
||||
panic!()
|
||||
}
|
||||
else
|
||||
{
|
||||
Ok(512)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_conv_table(matches: &getopts::Matches) -> Result<Option<ConversionTable>, Box<dyn Error>>
|
||||
{
|
||||
// TODO: Complete this stub fn
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
macro_rules! test_byte_parser (
|
||||
( $test_name:ident, $bs_str:expr, $bs:expr ) =>
|
||||
{
|
||||
#[test]
|
||||
fn $test_name()
|
||||
{
|
||||
let bs_str = String::from($bs_str);
|
||||
assert_eq!($bs, parse_bytes_with_opt_multiplier(bs_str).unwrap())
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
#[test]
|
||||
fn test_input_parser()
|
||||
{
|
||||
panic!()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_output_parser()
|
||||
{
|
||||
panic!()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_conv_options_parser()
|
||||
{
|
||||
panic!()
|
||||
}
|
||||
|
||||
test_byte_parser!(
|
||||
test_bytes_n,
|
||||
"765",
|
||||
765
|
||||
);
|
||||
test_byte_parser!(
|
||||
test_bytes_c,
|
||||
"13 c",
|
||||
13
|
||||
);
|
||||
|
||||
test_byte_parser!(
|
||||
test_bytes_w,
|
||||
"1 w",
|
||||
2
|
||||
);
|
||||
|
||||
test_byte_parser!(
|
||||
test_bytes_b,
|
||||
"1 b",
|
||||
512
|
||||
);
|
||||
|
||||
test_byte_parser!(
|
||||
test_bytes_k,
|
||||
"1 kB",
|
||||
1000
|
||||
);
|
||||
test_byte_parser!(
|
||||
test_bytes_K,
|
||||
"1 K",
|
||||
1024
|
||||
);
|
||||
test_byte_parser!(
|
||||
test_bytes_Ki,
|
||||
"1 KiB",
|
||||
1024
|
||||
);
|
||||
|
||||
test_byte_parser!(
|
||||
test_bytes_MB,
|
||||
"1 MB",
|
||||
1000*1000
|
||||
);
|
||||
test_byte_parser!(
|
||||
test_bytes_M,
|
||||
"1 M",
|
||||
1024*1024
|
||||
);
|
||||
test_byte_parser!(
|
||||
test_bytes_Mi,
|
||||
"1 MiB",
|
||||
1024*1024
|
||||
);
|
||||
|
||||
test_byte_parser!(
|
||||
test_bytes_GB,
|
||||
"1 GB",
|
||||
1000*1000*1000
|
||||
);
|
||||
test_byte_parser!(
|
||||
test_bytes_G,
|
||||
"1 G",
|
||||
1024*1024*1024
|
||||
);
|
||||
test_byte_parser!(
|
||||
test_bytes_Gi,
|
||||
"1 GiB",
|
||||
1024*1024*1024
|
||||
);
|
||||
|
||||
test_byte_parser!(
|
||||
test_bytes_TB,
|
||||
"1 TB",
|
||||
1000*1000*1000*1000
|
||||
);
|
||||
test_byte_parser!(
|
||||
test_bytes_T,
|
||||
"1 T",
|
||||
1024*1024*1024*1024
|
||||
);
|
||||
test_byte_parser!(
|
||||
test_bytes_Ti,
|
||||
"1 TiB",
|
||||
1024*1024*1024*1024
|
||||
);
|
||||
|
||||
test_byte_parser!(
|
||||
test_bytes_PB,
|
||||
"1 PB",
|
||||
1000*1000*1000*1000*1000
|
||||
);
|
||||
test_byte_parser!(
|
||||
test_bytes_P,
|
||||
"1 P",
|
||||
1024*1024*1024*1024*1024
|
||||
);
|
||||
test_byte_parser!(
|
||||
test_bytes_Pi,
|
||||
"1 PiB",
|
||||
1024*1024*1024*1024*1024
|
||||
);
|
||||
|
||||
test_byte_parser!(
|
||||
test_bytes_EB,
|
||||
"1 EB",
|
||||
1000*1000*1000*1000*1000*1000
|
||||
);
|
||||
test_byte_parser!(
|
||||
test_bytes_E,
|
||||
"1 E",
|
||||
1024*1024*1024*1024*1024*1024
|
||||
);
|
||||
test_byte_parser!(
|
||||
test_bytes_Ei,
|
||||
"1 EiB",
|
||||
1024*1024*1024*1024*1024*1024
|
||||
);
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_KB_multiplier_error()
|
||||
{
|
||||
let bs_str = String::from("2000 KB");
|
||||
|
||||
parse_bytes_with_opt_multiplier(bs_str).unwrap();
|
||||
}
|
||||
|
||||
}
|
329
src/uu/dd/src/test_dd_internal.rs
Normal file
329
src/uu/dd/src/test_dd_internal.rs
Normal file
|
@ -0,0 +1,329 @@
|
|||
use super::*;
|
||||
|
||||
use std::io::prelude::*;
|
||||
use std::io::BufReader;
|
||||
use std::fs;
|
||||
use md5::{ Md5, Digest, };
|
||||
use hex_literal::hex;
|
||||
// use tempfile::tempfile;
|
||||
// TODO: (Maybe) Use tempfiles in the tests.
|
||||
|
||||
macro_rules! make_hash_test (
|
||||
( $test_id:ident, $test_name:expr, $src:expr, $exp:expr ) =>
|
||||
{
|
||||
#[test]
|
||||
fn $test_id()
|
||||
{
|
||||
let tmp_fname = format!("./test-resources/FAILED-{}.test", $test_name);
|
||||
|
||||
let i = Input {
|
||||
src: $src,
|
||||
ibs: 256,
|
||||
output_progress: false,
|
||||
};
|
||||
|
||||
let o = Output {
|
||||
dst: File::create(&tmp_fname).unwrap(),
|
||||
obs: 1024,
|
||||
conv_table: None,
|
||||
};
|
||||
|
||||
dd(i,o).unwrap();
|
||||
|
||||
let res = {
|
||||
let res = File::open(&tmp_fname).unwrap();
|
||||
let res = BufReader::new(res);
|
||||
|
||||
let mut h = Md5::new();
|
||||
for b in res.bytes()
|
||||
{
|
||||
h.update([b.unwrap()]);
|
||||
}
|
||||
|
||||
h.finalize()
|
||||
};
|
||||
|
||||
assert_eq!(hex!($exp), res[..]);
|
||||
|
||||
fs::remove_file(&tmp_fname).unwrap();
|
||||
}
|
||||
};
|
||||
( $test_id:ident, $test_name:expr, $i:expr, $o:expr, $exp:expr ) =>
|
||||
{
|
||||
#[test]
|
||||
fn $test_id()
|
||||
{
|
||||
let tmp_fname = format!("./test-resources/FAILED-{}.test", $test_name);
|
||||
|
||||
let o = Output {
|
||||
dst: File::create(&tmp_fname).unwrap(),
|
||||
obs: $o.obs,
|
||||
conv_table: $o.conv_table,
|
||||
};
|
||||
|
||||
dd($i,o).unwrap();
|
||||
|
||||
let res = {
|
||||
let res = File::open(&tmp_fname).unwrap();
|
||||
let res = BufReader::new(res);
|
||||
|
||||
let mut h = Md5::new();
|
||||
for b in res.bytes()
|
||||
{
|
||||
h.update([b.unwrap()]);
|
||||
}
|
||||
|
||||
h.finalize()
|
||||
};
|
||||
|
||||
assert_eq!(hex!($exp), res[..]);
|
||||
|
||||
fs::remove_file(&tmp_fname).unwrap();
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
macro_rules! make_spec_test (
|
||||
( $test_id:ident, $test_name:expr, $i:expr, $o:expr, $spec:expr ) =>
|
||||
{
|
||||
#[test]
|
||||
fn $test_id()
|
||||
{
|
||||
let tmp_fname = format!("./test-resources/FAILED-{}.test", $test_name);
|
||||
|
||||
let o = Output {
|
||||
dst: File::create(&tmp_fname).unwrap(),
|
||||
obs: $o.obs,
|
||||
conv_table: $o.conv_table,
|
||||
};
|
||||
|
||||
dd($i,o).unwrap();
|
||||
|
||||
let res = File::open(&tmp_fname).unwrap();
|
||||
let res = BufReader::new(res);
|
||||
|
||||
let spec = BufReader::new($spec);
|
||||
|
||||
for (b_res, b_spec) in res.bytes().zip(spec.bytes())
|
||||
{
|
||||
assert_eq!(b_res.unwrap(),
|
||||
b_spec.unwrap());
|
||||
}
|
||||
|
||||
fs::remove_file(&tmp_fname).unwrap();
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
make_hash_test!(
|
||||
empty_file_test,
|
||||
"stdio-empty-file",
|
||||
io::empty(),
|
||||
"d41d8cd98f00b204e9800998ecf8427e"
|
||||
);
|
||||
|
||||
make_hash_test!(
|
||||
zeros_4k_test,
|
||||
"zeros-4k",
|
||||
File::open("./test-resources/zeros-620f0b67a91f7f74151bc5be745b7110.test").unwrap(),
|
||||
"620f0b67a91f7f74151bc5be745b7110"
|
||||
);
|
||||
|
||||
make_hash_test!(
|
||||
ones_4k_test,
|
||||
"ones-4k",
|
||||
File::open("./test-resources/ones-6ae59e64850377ee5470c854761551ea.test").unwrap(),
|
||||
"6ae59e64850377ee5470c854761551ea"
|
||||
);
|
||||
|
||||
make_hash_test!(
|
||||
deadbeef_32k_test,
|
||||
"deadbeef-32k",
|
||||
File::open("./test-resources/deadbeef-18d99661a1de1fc9af21b0ec2cd67ba3.test").unwrap(),
|
||||
"18d99661a1de1fc9af21b0ec2cd67ba3"
|
||||
);
|
||||
|
||||
make_hash_test!(
|
||||
random_73k_test,
|
||||
"random-73k",
|
||||
File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap(),
|
||||
"5828891cb1230748e146f34223bbd3b5"
|
||||
);
|
||||
|
||||
make_spec_test!(
|
||||
atoe_conv_spec_test,
|
||||
"atoe-conv-spec-test",
|
||||
Input {
|
||||
src: File::open("./test-resources/seq-byte-values-b632a992d3aed5d8d1a59cc5a5a455ba.test").unwrap(),
|
||||
ibs: 512,
|
||||
output_progress: false,
|
||||
},
|
||||
Output {
|
||||
dst: Vec::new(), // unused!
|
||||
obs: 512,
|
||||
conv_table: Some(ASCII_TO_EBCDIC),
|
||||
},
|
||||
File::open("./test-resources/gnudd-conv-atoe-seq-byte-values.spec").unwrap()
|
||||
);
|
||||
|
||||
make_spec_test!(
|
||||
etoa_conv_spec_test,
|
||||
"etoa-conv-spec-test",
|
||||
Input {
|
||||
src: File::open("./test-resources/seq-byte-values-b632a992d3aed5d8d1a59cc5a5a455ba.test").unwrap(),
|
||||
ibs: 512,
|
||||
output_progress: false,
|
||||
},
|
||||
Output {
|
||||
dst: Vec::new(), // unused!
|
||||
obs: 512,
|
||||
conv_table: Some(EBCDIC_TO_ASCII),
|
||||
},
|
||||
File::open("./test-resources/gnudd-conv-etoa-seq-byte-values.spec").unwrap()
|
||||
);
|
||||
|
||||
make_spec_test!(
|
||||
atoibm_conv_spec_test,
|
||||
"atoibm-conv-spec-test",
|
||||
Input {
|
||||
src: File::open("./test-resources/seq-byte-values-b632a992d3aed5d8d1a59cc5a5a455ba.test").unwrap(),
|
||||
ibs: 512,
|
||||
output_progress: false,
|
||||
},
|
||||
Output {
|
||||
dst: Vec::new(), // unused!
|
||||
obs: 512,
|
||||
conv_table: Some(ASCII_TO_IBM),
|
||||
},
|
||||
File::open("./test-resources/gnudd-conv-atoibm-seq-byte-values.spec").unwrap()
|
||||
);
|
||||
|
||||
make_spec_test!(
|
||||
lcase_ascii_to_ucase_ascii,
|
||||
"lcase_ascii_to_ucase_ascii",
|
||||
Input {
|
||||
src: File::open("./test-resources/lcase-ascii.test").unwrap(),
|
||||
ibs: 512,
|
||||
output_progress: false,
|
||||
},
|
||||
Output {
|
||||
dst: Vec::new(), // unused!
|
||||
obs: 512,
|
||||
conv_table: Some(LCASE_TO_UCASE),
|
||||
},
|
||||
File::open("./test-resources/ucase-ascii.test").unwrap()
|
||||
);
|
||||
|
||||
make_spec_test!(
|
||||
ucase_ascii_to_lcase_ascii,
|
||||
"ucase_ascii_to_lcase_ascii",
|
||||
Input {
|
||||
src: File::open("./test-resources/ucase-ascii.test").unwrap(),
|
||||
ibs: 512,
|
||||
output_progress: false,
|
||||
},
|
||||
Output {
|
||||
dst: Vec::new(), // unused!
|
||||
obs: 512,
|
||||
conv_table: Some(UCASE_TO_LCASE),
|
||||
},
|
||||
File::open("./test-resources/lcase-ascii.test").unwrap()
|
||||
);
|
||||
|
||||
#[test]
|
||||
fn all_valid_ascii_ebcdic_ascii_roundtrip_conv_test()
|
||||
{
|
||||
// ASCII->EBCDIC
|
||||
let test_name = "all-valid-ascii-to-ebcdic";
|
||||
let tmp_fname_ae = format!("./test-resources/FAILED-{}.test", test_name);
|
||||
|
||||
let i = Input {
|
||||
src: File::open("./test-resources/all-valid-ascii-chars-37eff01866ba3f538421b30b7cbefcac.test").unwrap(),
|
||||
ibs: 256,
|
||||
output_progress: false,
|
||||
};
|
||||
|
||||
let o = Output {
|
||||
dst: File::create(&tmp_fname_ae).unwrap(),
|
||||
obs: 1024,
|
||||
conv_table: Some(ASCII_TO_EBCDIC),
|
||||
};
|
||||
|
||||
dd(i,o).unwrap();
|
||||
|
||||
// EBCDIC->ASCII
|
||||
let test_name = "all-valid-ebcdic-to-ascii";
|
||||
let tmp_fname_ea = format!("./test-resources/FAILED-{}.test", test_name);
|
||||
|
||||
let i = Input {
|
||||
src: File::open(&tmp_fname_ae).unwrap(),
|
||||
ibs: 256,
|
||||
output_progress: false,
|
||||
};
|
||||
|
||||
let o = Output {
|
||||
dst: File::create(&tmp_fname_ea).unwrap(),
|
||||
obs: 1024,
|
||||
conv_table: Some(EBCDIC_TO_ASCII),
|
||||
};
|
||||
|
||||
dd(i,o).unwrap();
|
||||
|
||||
let res = {
|
||||
let res = File::open(&tmp_fname_ea).unwrap();
|
||||
let res = BufReader::new(res);
|
||||
|
||||
let mut h = Md5::new();
|
||||
for b in res.bytes()
|
||||
{
|
||||
h.update([b.unwrap()]);
|
||||
}
|
||||
|
||||
h.finalize()
|
||||
};
|
||||
|
||||
assert_eq!(hex!("37eff01866ba3f538421b30b7cbefcac"), res[..]);
|
||||
|
||||
fs::remove_file(&tmp_fname_ae).unwrap();
|
||||
fs::remove_file(&tmp_fname_ea).unwrap();
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn copy_zerofile_from_args()
|
||||
// {
|
||||
// let spec = File::open("./test-resources/zeros-620f0b67a91f7f74151bc5be745b7110.test").unwrap();
|
||||
// let tmp_fname = format!("./test-resources/{}", "zeros-from-args.test");
|
||||
//
|
||||
// let args = vec![
|
||||
// String::from("if=./test-resources/zeros-620f0b67a91f7f74151bc5be745b7110.test"),
|
||||
// String::from(&tmp_fname),
|
||||
// ];
|
||||
// let args = Args { args };
|
||||
//
|
||||
// uumain(args);
|
||||
//
|
||||
// let res = File::open(&tmp_fname).unwrap();
|
||||
// let res = BufReader::new(res);
|
||||
//
|
||||
// let spec = BufReader::new(spec);
|
||||
//
|
||||
// for (b_res, b_spec) in res.bytes().zip(spec.bytes())
|
||||
// {
|
||||
// assert_eq!(b_res.unwrap(),
|
||||
// b_spec.unwrap());
|
||||
// }
|
||||
//
|
||||
// fs::remove_file(&tmp_fname).unwrap();
|
||||
// }
|
||||
|
||||
//use rand::prelude::*;
|
||||
//#[test]
|
||||
//fn make_test_data()
|
||||
//{
|
||||
// let mut f = File::create("./test-resources/random-walk-through-the-ascii-ranged-forest.test").unwrap();
|
||||
// // let mut rng = rand::thread_rng();
|
||||
|
||||
// for _ in 0..65536 {
|
||||
// f.write(&[c]).unwrap();
|
||||
// }
|
||||
//}
|
|
@ -1,7 +1,61 @@
|
|||
use crate::common::util::*;
|
||||
|
||||
use std::io::prelude::*;
|
||||
use std::io::BufReader;
|
||||
use std::fs::{self, File};
|
||||
|
||||
#[test]
|
||||
fn fail_from_test_dd()
|
||||
fn dd_zeros_to_stdout_test_from_args()
|
||||
{
|
||||
panic!()
|
||||
new_ucmd!()
|
||||
.args(&[
|
||||
"if=../../src/uu/dd/test-resources/zeros-620f0b67a91f7f74151bc5be745b7110.test",
|
||||
])
|
||||
.succeeds()
|
||||
.stdout_only(
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||
"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dd_ones_to_file_test_from_args()
|
||||
{
|
||||
let tmp_fname = "../../src/uu/dd/test-resources/FAILED-ones-to-file-from-args.test";
|
||||
|
||||
new_ucmd!()
|
||||
.args(&[
|
||||
"if=../../src/uu/dd/test-resources/ones-6ae59e64850377ee5470c854761551ea.test",
|
||||
&format!("of={}", &tmp_fname),
|
||||
])
|
||||
.succeeds();
|
||||
|
||||
let res = File::open(&tmp_fname).unwrap();
|
||||
let res = BufReader::new(res);
|
||||
|
||||
let spec = File::open("../../src/uu/dd/test-resources/ones-6ae59e64850377ee5470c854761551ea.test").unwrap();
|
||||
let spec = BufReader::new(spec);
|
||||
|
||||
for (b_res, b_spec) in res.bytes().zip(spec.bytes())
|
||||
{
|
||||
assert_eq!(b_res.unwrap(),
|
||||
b_spec.unwrap());
|
||||
}
|
||||
|
||||
fs::remove_file(&tmp_fname).unwrap();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue