1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 03:27:44 +00:00

Implements project testfing from root.

- conv=FLAG testing. (1) WIP conv=nocreat
- iflag & oflag testing.
- conv=CONV ascii,...,ucase,...,block,...sync tests at unit-test-level
  (project root is todo)
This commit is contained in:
Tyler 2021-06-30 14:47:48 -07:00
parent 47464f50a1
commit 17cfba41cc
29 changed files with 1376 additions and 187 deletions

148
Cargo.lock generated
View file

@ -98,16 +98,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1339a1042f5d9f295737ad4d9a6ab6bf81c84a933dba110b9200cd6d1448b814"
dependencies = [
"byte-tools",
"generic-array 0.8.4",
]
[[package]]
name = "block-buffer"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
"generic-array 0.14.4",
"generic-array",
]
[[package]]
@ -569,16 +560,7 @@ version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a"
dependencies = [
"generic-array 0.8.4",
]
[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array 0.14.4",
"generic-array",
]
[[package]]
@ -655,16 +637,6 @@ dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getopts"
version = "0.2.21"
@ -682,7 +654,18 @@ checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
dependencies = [
"cfg-if 1.0.0",
"libc",
"wasi",
"wasi 0.9.0+wasi-snapshot-preview1",
]
[[package]]
name = "getrandom"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
"cfg-if 1.0.0",
"libc",
"wasi 0.10.2+wasi-snapshot-preview1",
]
[[package]]
@ -718,12 +701,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa"
[[package]]
name = "hex-literal"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5af1f635ef1bc545d78392b136bfe1c9809e029023c84a3638a864a10b8819c8"
[[package]]
name = "hostname"
version = "0.3.1"
@ -832,17 +809,6 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
[[package]]
name = "md-5"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15"
dependencies = [
"block-buffer 0.9.0",
"digest 0.9.0",
"opaque-debug",
]
[[package]]
name = "md5"
version = "0.3.8"
@ -973,12 +939,6 @@ version = "11.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]]
name = "paste"
version = "0.1.18"
@ -1115,14 +1075,26 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [
"getrandom",
"getrandom 0.1.16",
"libc",
"rand_chacha",
"rand_chacha 0.2.2",
"rand_core 0.5.1",
"rand_hc",
"rand_hc 0.2.0",
"rand_pcg",
]
[[package]]
name = "rand"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
dependencies = [
"libc",
"rand_chacha 0.3.1",
"rand_core 0.6.3",
"rand_hc 0.3.1",
]
[[package]]
name = "rand_chacha"
version = "0.2.2"
@ -1133,6 +1105,16 @@ dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core 0.6.3",
]
[[package]]
name = "rand_core"
version = "0.3.1"
@ -1154,7 +1136,16 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
dependencies = [
"getrandom",
"getrandom 0.1.16",
]
[[package]]
name = "rand_core"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
"getrandom 0.2.3",
]
[[package]]
@ -1166,6 +1157,15 @@ dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "rand_hc"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
dependencies = [
"rand_core 0.6.3",
]
[[package]]
name = "rand_pcg"
version = "0.2.1"
@ -1366,11 +1366,11 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d963c78ce367df26d7ea8b8cc655c651b42e8a1e584e869c1e17dae3ccb116a"
dependencies = [
"block-buffer 0.2.0",
"block-buffer",
"byte-tools",
"digest 0.6.2",
"digest",
"fake-simd",
"generic-array 0.8.4",
"generic-array",
]
[[package]]
@ -1379,10 +1379,10 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26405905b6a56a94c60109cfda62610507ac14a65be531f5767dec5c5a8dd6a0"
dependencies = [
"block-buffer 0.2.0",
"block-buffer",
"byte-tools",
"digest 0.6.2",
"generic-array 0.8.4",
"digest",
"generic-array",
]
[[package]]
@ -1759,10 +1759,10 @@ dependencies = [
"debug_print",
"gcd",
"getopts",
"hex-literal",
"libc",
"md-5",
"rand 0.8.4",
"signal-hook",
"tempfile",
"uucore",
"uucore_procs",
]
@ -1854,7 +1854,7 @@ dependencies = [
"paste",
"quickcheck",
"rand 0.7.3",
"rand_chacha",
"rand_chacha 0.2.2",
"smallvec",
"uucore",
"uucore_procs",
@ -1902,7 +1902,7 @@ version = "0.0.4"
dependencies = [
"blake2-rfc",
"clap",
"digest 0.6.2",
"digest",
"hex",
"libc",
"md5",
@ -2621,12 +2621,6 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "void"
version = "1.0.2"
@ -2650,6 +2644,12 @@ version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "wasm-bindgen"
version = "0.2.71"

View file

@ -17,7 +17,7 @@ path = "src/dd.rs"
[dependencies]
byte-unit = "4.0"
debug_print = "1.0"
# Probably best to keep this identical to the version of getopts in the uucore crate
# Probably best to keep the getopts version identical to the version of getopts in the uucore crate
getopts = "<= 0.2.21"
gcd = "2.0"
libc = "0.2"
@ -26,8 +26,8 @@ uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
[dev-dependencies]
md-5 = "0.9"
hex-literal = "0.3"
rand = "0.8"
tempfile = "^3"
[[bin]]
name = "dd"

View file

@ -361,19 +361,32 @@ impl<R: Read> Read for Input<R>
{
fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize>
{
match self.src.read(&mut buf)
let mut base_idx = 0;
let tlen = buf.len();
loop
{
Ok(len) =>
Ok(len),
Err(e) =>
if !self.cflags.noerror
match self.src.read(&mut buf[base_idx..])
{
Err(e)
Ok(0) =>
return Ok(base_idx),
Ok(rlen) if self.iflags.fullblock =>
{
base_idx += rlen;
if base_idx >= tlen
{
return Ok(tlen)
}
else
{
Ok(0)
},
Ok(len) =>
return Ok(len),
Err(e) if e.kind() == io::ErrorKind::Interrupted =>
continue,
Err(_) if self.cflags.noerror =>
return Ok(base_idx),
Err(e) =>
return Err(e),
}
}
}
}
@ -529,6 +542,11 @@ fn make_unix_oflags(oflags: &OFlags) -> Option<libc::c_int>
{
let mut flag = 0;
// oflag=FLAG
if oflags.append
{
flag |= libc::O_APPEND;
}
if oflags.direct
{
flag |= libc::O_DIRECT;
@ -585,9 +603,11 @@ impl Output<File> {
let mut dst = {
let mut opts = OpenOptions::new();
opts.write(true)
.create(true)
.truncate(!cflags.notrunc)
.append(oflags.append)
.create_new(cflags.excl || !cflags.nocreat)
.truncate(!cflags.notrunc);
// 'create_new' overrides 'create'
.create_new(cflags.excl && !cflags.nocreat);
if cfg!(unix)
{
@ -1484,47 +1504,57 @@ fn append_dashes_if_not_present(mut acc: Vec<String>, s: &String) -> Vec<String>
}
}
macro_rules! unpack_or_rtn (
($i:expr, $o:expr) =>
{{
match ($i, $o)
{
(Ok(i), Ok(o)) =>
(i,o),
(Err(e), _) =>
{
eprintln!("dd Error: {}", e);
return RTN_FAILURE;
},
(_, Err(e)) =>
{
eprintln!("dd Error: {}", e);
return RTN_FAILURE;
},
}
}};
);
pub fn uumain(args: impl uucore::Args) -> i32
{
let dashed_args = args.collect_str()
.iter()
.fold(Vec::new(), append_dashes_if_not_present);
let matches = build_app!().parse(dashed_args);
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, o) = unpack_or_rtn!(Input::<File>::new(&matches), Output::<File>::new(&matches));
dd_fileout(i,o)
},
(false, true) =>
{
let (i, o) = unpack_or_rtn!(Input::<io::Stdin>::new(&matches), Output::<File>::new(&matches));
dd_fileout(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");
let (i, o) = unpack_or_rtn!(Input::<File>::new(&matches), Output::<io::Stdout>::new(&matches));
dd_stdout(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_fileout(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");
let (i, o) = unpack_or_rtn!(Input::<io::Stdin>::new(&matches), Output::<io::Stdout>::new(&matches));
dd_stdout(i,o)
},

View file

@ -1,19 +1,5 @@
use super::*;
struct LazyReader<R: Read>
{
src: R,
}
impl<R: Read> Read for LazyReader<R>
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize>
{
let reduced = cmp::max(buf.len() / 2, 1);
self.src.read(&mut buf[..reduced])
}
}
macro_rules! make_sync_test (
( $test_id:ident, $test_name:expr, $src:expr, $sync:expr, $ibs:expr, $obs:expr, $spec:expr ) =>
{

View file

@ -5,14 +5,10 @@ mod conversion_tests;
mod block_unblock_tests;
mod conv_sync_tests;
use rand::prelude::*;
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.
const DEFAULT_CFO: OConvFlags = OConvFlags {
sparse: false,
@ -60,6 +56,40 @@ const DEFAULT_OFLAGS: OFlags = OFlags {
seek_bytes: false,
};
struct LazyReader<R: Read>
{
src: R,
}
impl<R: Read> Read for LazyReader<R>
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize>
{
let reduced = cmp::max(buf.len() / 2, 1);
self.src.read(&mut buf[..reduced])
}
}
struct FickleReader<R: Read>
{
src: R,
}
impl<R: Read> Read for FickleReader<R>
{
fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize>
{
if rand::random()
{
self.src.read(&mut buf)
}
else
{
Ok(0)
}
}
}
#[macro_export]
macro_rules! icf (
() =>

View file

@ -212,6 +212,86 @@ make_io_test!(
File::open("./test-resources/gnudd-random-first-32k.spec").unwrap()
);
make_io_test!(
random_73k_test_lazy_fullblock,
"random-73k-test-lazy-fullblock",
Input {
src: LazyReader {
src: File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap()
},
non_ascii: false,
ibs: 521,
xfer_stats: None,
count: None,
cflags: icf!(),
iflags: IFlags {
fullblock: true,
cio: false,
direct: false,
directory: false,
dsync: false,
sync: false,
nocache: false,
nonblock: false,
noatime: false,
noctty: false,
nofollow: false,
nolinks: false,
binary: false,
text: false,
count_bytes: false,
skip_bytes: false,
},
},
Output {
dst: DST_PLACEHOLDER,
obs: 1031,
cflags: DEFAULT_CFO,
oflags: DEFAULT_OFLAGS,
},
File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap()
);
make_io_test!(
random_73k_test_fickle_fullblock,
"random-73k-test-fickle-fullblock",
Input {
src: FickleReader {
src: File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap()
},
non_ascii: false,
ibs: 521,
xfer_stats: None,
count: None,
cflags: icf!(),
iflags: IFlags {
fullblock: true,
cio: false,
direct: false,
directory: false,
dsync: false,
sync: false,
nocache: false,
nonblock: false,
noatime: false,
noctty: false,
nofollow: false,
nolinks: false,
binary: false,
text: false,
count_bytes: false,
skip_bytes: false,
},
},
Output {
dst: DST_PLACEHOLDER,
obs: 1031,
cflags: DEFAULT_CFO,
oflags: DEFAULT_OFLAGS,
},
File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap()
);
// Test internal buffer size fn
#[test]
fn bsize_test_primes()

View file

@ -33,7 +33,53 @@ pub enum ParseError
impl std::fmt::Display for ParseError
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "dd-args: Parse Error")
match self
{
Self::MultipleFmtTable =>
{
write!(f, "Only one of conv=ascii conv=ebcdic or conv=ibm may be specified")
},
Self::MultipleUCaseLCase =>
{
write!(f, "Only one of conv=lcase or conv=ucase may be specified")
},
Self::MultipleBlockUnblock =>
{
write!(f, "Only one of conv=block or conv=unblock may be specified")
},
Self::MultipleExclNoCreat =>
{
write!(f, "Only one ov conv=excl or conv=nocreat may be specified")
},
Self::FlagNoMatch(arg) =>
{
write!(f, "Unrecognized iflag=FLAG or oflag=FLAG -> {}", arg)
},
Self::ConvFlagNoMatch(arg) =>
{
write!(f, "Unrecognized conv=CONV -> {}", arg)
},
Self::NoMatchingMultiplier(arg) =>
{
write!(f, "Unrecognized byte multiplier -> {}", arg)
},
Self::ByteStringContainsNoValue(arg) =>
{
write!(f, "Unrecognized byte value -> {}", arg)
},
Self::MultiplierStringWouldOverflow(arg) =>
{
write!(f, "Multiplier string would overflow on current system -> {}", arg)
},
Self::BlockUnblockWithoutCBS =>
{
write!(f, "conv=block or conv=unblock specified without cbs=N")
},
Self::StatusLevelNotRecognized(arg) =>
{
write!(f, "status=LEVEL not recognized -> {}", arg)
},
}
}
}
@ -270,7 +316,9 @@ fn parse_bytes_only(s: &str) -> Result<usize, ParseError>
fn parse_bytes_with_opt_multiplier(s: String) -> Result<usize, ParseError>
{
if let Some(idx) = s.find(char::is_alphabetic)
match s.find(char::is_alphabetic)
{
Some(idx) =>
{
let base = parse_bytes_only(&s[..idx])?;
let mult = parse_multiplier(&s[idx..])?;
@ -284,9 +332,8 @@ fn parse_bytes_with_opt_multiplier(s: String) -> Result<usize, ParseError>
Err(ParseError::MultiplierStringWouldOverflow(s))
}
}
else
{
parse_bytes_only(&s)
_ =>
parse_bytes_only(&s),
}
}

View file

@ -1,5 +1,107 @@
use crate::common::util::*;
use std::io::{BufReader, Read, Write};
use std::path::{Path, PathBuf};
use std::fs::{self, OpenOptions, File};
use std::time::{Duration, SystemTime};
use tempfile::tempfile;
macro_rules! inf
{
($fname:expr) =>
{{
&format!("if={}", $fname)
}};
}
macro_rules! of
{
($fname:expr) =>
{{
&format!("of={}", $fname)
}};
}
macro_rules! fixture_path
{
($fname:expr) =>
{{
PathBuf::from(format!("./tests/fixtures/dd/{}", $fname))
}};
}
macro_rules! assert_fixture_exists
{
($fname:expr) =>
{{
let fpath = fixture_path!($fname);
if !fpath.exists()
{
panic!("Fixture missing: {:?}", fpath);
}
}};
}
macro_rules! assert_fixture_not_exists
{
($fname:expr) =>
{{
let fpath = PathBuf::from(format!("./fixtures/dd/{}", $fname));
if fpath.exists()
{
panic!("Fixture present: {:?}", fpath);
}
}};
}
macro_rules! build_test_file {
($fp:expr, $data:expr) => {{
OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open($fp)
.unwrap()
.write_all($data)
.unwrap()
}};
}
macro_rules! cmp_file (
($spec:expr, $test:expr) =>
{
let specfile_len = $spec.metadata().unwrap().len();
let testfile_len = $test.metadata().unwrap().len();
assert_eq!(testfile_len, specfile_len);
let spec = BufReader::new($spec);
let test = BufReader::new($test);
for (b_spec, b_test) in spec.bytes().zip(test.bytes())
{
assert_eq!(b_spec.unwrap(),
b_test.unwrap());
}
};
);
fn build_ascii_block(n: usize) -> Vec<u8>
{
(0..=127)
.cycle()
.take(n)
.collect()
}
fn build_ebcdic_block(n: usize) -> Vec<u8>
{
(0..=255)
.cycle()
.take(n)
.collect()
}
// Sanity Tests
#[test]
fn version()
{
@ -16,16 +118,6 @@ fn help()
.succeeds();
}
fn build_ascii_block(n: usize) -> Vec<u8>
{
vec!['a', 'b', 'c', 'd', 'e', 'f']
.into_iter()
.map(|c| c as u8)
.cycle()
.take(n)
.collect()
}
#[test]
fn test_stdin_stdout()
{
@ -34,10 +126,13 @@ fn test_stdin_stdout()
new_ucmd!()
.args(&["status=none"])
.pipe_in(input)
.succeeds()
.run()
.no_stderr()
.stdout_only(output);
}
// Top-Level Items
// count=N, skip=N, status=LEVEL, conv=FLAG, *flag=FLAG
#[test]
fn test_stdin_stdout_count()
{
@ -51,7 +146,8 @@ fn test_stdin_stdout_count()
"ibs=128",
])
.pipe_in(input)
.succeeds()
.run()
.no_stderr()
.stdout_only(output);
}
@ -68,7 +164,8 @@ fn test_stdin_stdout_count_bytes()
"iflag=count_bytes",
])
.pipe_in(input)
.succeeds()
.run()
.no_stderr()
.stdout_only(output);
}
@ -85,7 +182,8 @@ fn test_stdin_stdout_skip()
"ibs=128",
])
.pipe_in(input)
.succeeds()
.run()
.no_stderr()
.stdout_only(output);
}
@ -103,10 +201,47 @@ fn test_stdin_stdout_skip_bytes()
"iflag=skip_bytes",
])
.pipe_in(input)
.succeeds()
.run()
.no_stderr()
.stdout_only(output);
}
#[test]
fn test_stdin_stdout_skip_w_multiplier()
{
let input = build_ascii_block(10*1024);
let output = String::from_utf8(input[5*1024..].to_vec()).unwrap();
new_ucmd!()
.args(&[
"status=none",
"skip=5K",
"iflag=skip_bytes"
])
.pipe_in(input)
.run()
.no_stderr()
.stdout_is(output)
.success();
}
#[test]
fn test_stdin_stdout_count_w_multiplier()
{
let input = build_ascii_block(5*1024);
let output = String::from_utf8(input[..2*1024].to_vec()).unwrap();
new_ucmd!()
.args(&[
"status=none",
"count=2KiB",
"iflag=count_bytes",
])
.pipe_in(input)
.run()
.no_stderr()
.stdout_is(output)
.success();
}
#[test]
fn test_final_stats_noxfer()
{
@ -133,49 +268,246 @@ fn test_final_stats_unspec()
acc
});
new_ucmd!()
.succeeds()
.stderr_only(&output);
.run()
.stderr_only(&output)
.success();
}
#[test]
fn test_self_transfer()
fn test_excl_causes_failure_when_present()
{
panic!();
// TODO: Make new copy per-test
new_ucmd!()
.args(&[
"conv=notruc",
"if=../fixtures/dd/zero-256k.copy",
"of=../fixtures/dd/zero-256k.copy",
let fname = "this-file-exists-excl.txt";
assert_fixture_exists!(&fname);
let (_fix, mut ucmd) = at_and_ucmd!();
ucmd.args(&[
"of=this-file-exists-excl.txt",
"conv=excl",
])
.succeeds();
assert!(false/* Must check that zero256k.copy still == zero-256k.txt */)
.fails();
}
#[cfg(unix)]
#[test]
fn test_null()
fn test_atime_updated()
{
let fname = "this-file-exists-no-noatime.txt";
assert_fixture_exists!(&fname);
let (fix, mut ucmd) = at_and_ucmd!();
ucmd.args(&[
"status=none",
inf!(fname),
]);
let pre_atime = fix.metadata(&fname).accessed().unwrap();
ucmd.pipe_in("")
.run()
.no_stderr()
.success();
let post_atime = fix.metadata(&fname).accessed().unwrap();
assert!(pre_atime != post_atime);
}
#[test]
fn test_noatime_does_not_update_infile_atime()
{
let fname = "this-ifile-exists-noatime.txt";
assert_fixture_exists!(&fname);
let (fix, mut ucmd) = at_and_ucmd!();
ucmd.args(&[
"status=none",
"iflag=noatime",
inf!(fname),
]);
let pre_atime = fix.metadata(&fname).accessed().unwrap();
ucmd.run()
.no_stderr()
.success();
let post_atime = fix.metadata(&fname).accessed().unwrap();
assert_eq!(pre_atime, post_atime);
}
#[test]
fn test_noatime_does_not_update_ofile_atime()
{
let fname = "this-ofile-exists-noatime.txt";
assert_fixture_exists!(&fname);
let (fix, mut ucmd) = at_and_ucmd!();
ucmd.args(&[
"status=none",
"oflag=noatime",
of!(fname),
]);
let pre_atime = fix.metadata(&fname).accessed().unwrap();
ucmd.pipe_in("")
.run()
.no_stderr()
.success();
let post_atime = fix.metadata(&fname).accessed().unwrap();
assert_eq!(pre_atime, post_atime);
}
#[test]
fn test_nocreat_causes_failure_when_not_present()
{
let fname = "this-file-does-not-exist.txt";
assert_fixture_not_exists!(&fname);
let (fix, mut ucmd) = at_and_ucmd!();
ucmd.args(&[
"conv=nocreat",
of!(&fname),
])
.run();
assert!(!fix.file_exists(&fname));
ucmd.fails();
}
#[test]
fn test_notrunc_does_not_truncate()
{
// Set up test if needed (eg. after failure)
let fname = "this-file-exists-notrunc.txt";
let fpath = fixture_path!(fname);
match fpath.metadata()
{
Ok(m) if m.len() == 256 => {},
_ =>
build_test_file!(&fpath, &build_ascii_block(256)),
}
let (fix, mut ucmd) = at_and_ucmd!();
ucmd.args(&[
"status=none",
"conv=notrunc",
of!(&fname),
"if=null.txt",
])
.run()
.no_stdout()
.no_stderr()
.success();
assert_eq!(256, fix.metadata(&fname).len());
}
#[test]
fn test_existing_file_truncated()
{
// Set up test if needed (eg. after failure)
let fname = "this-file-exists-truncated.txt";
let fpath = fixture_path!(fname);
match fpath.metadata()
{
Ok(m) if m.len() == 256 => {},
_ =>
build_test_file!(&fpath, &vec![0; 256]),
}
let (fix, mut ucmd) = at_and_ucmd!();
ucmd.args(&[
"status=none",
"if=null.txt",
of!(fname),
])
.run()
.no_stdout()
.no_stderr()
.success();
assert_eq!(0, fix.metadata(&fname).len());
}
#[test]
fn test_null_stats()
{
let stats = vec![
"0+0 records in",
"0+0 records out",
"0 bytes (0 B, 0 B) copied, 0.0 s, 0 B/s",
"0+0 records in\n",
"0+0 records out\n",
"0 bytes (0 B, 0 B) copied, 0.0 s, 0 B/s\n",
];
let stats = stats.into_iter()
.fold(String::new(), | mut acc, s | {
acc.push_str(s);
acc.push('\n');
acc
});
new_ucmd!()
.args(&[
"if=/dev/null",
"if=null.txt",
])
.succeeds()
.run()
.stderr_only(stats)
.stdout_only("");
.success();
}
#[test]
fn test_null_fullblock()
{
new_ucmd!()
.args(&[
"if=null.txt",
"status=none",
"iflag=fullblock",
])
.run()
.no_stdout()
.no_stderr()
.success();
}
#[cfg(unix)]
// #[ignore] // See note below before running this test!
#[test]
fn test_fullblock()
{
let tname = "fullblock-from-urand";
let tmp_fn = format!("TESTFILE-{}.tmp", &tname);
let stats = vec![
"1+0 records in\n",
"1+0 records out\n",
"134217728 bytes (134 MB, 128 MiB) copied,",
];
let stats = stats.into_iter()
.fold(String::new(), | mut acc, s | {
acc.push_str(s);
acc
});
let res = new_ucmd!()
.args(&[
"if=/dev/urandom",
of!(&tmp_fn),
"bs=128M",
// Note: In order for this test to actually test iflag=fullblock, the bs=VALUE
// must be big enough to 'overwhelm' urandom's store of bytes.
// Try executing 'dd if=/dev/urandom bs=128M count=1' (i.e without iflag=fullblock).
// The stats should contain the line: '0+1 records in' indicating a partial read.
// Since my system only copies 32 MiB without fullblock, I expect 128 MiB to be
// a reasonable value for testing most systems.
"count=1",
"iflag=fullblock",
])
.run();
res.success();
let res_stats = &res.stderr[..stats.len()];
assert_eq!(&stats, res_stats);
}
// Fileio
#[test]
fn test_ys_to_stdout()
{
@ -188,10 +520,13 @@ fn test_ys_to_stdout()
new_ucmd!()
.args(&[
"if=../fixtures/dd/y-nl-1k.txt",
"status=none",
"if=y-nl-1k.txt",
])
.run()
.stdout_only(output);
.no_stderr()
.stdout_is(output)
.success();
}
#[test]
@ -201,9 +536,176 @@ fn test_zeros_to_stdout()
let output = String::from_utf8(output).unwrap();
new_ucmd!()
.args(&[
"if=../fixtures/dd/zero-256k.txt",
"status=none",
"if=zero-256k.txt",
])
.run()
.stdout_only(output);
.no_stderr()
.stdout_is(output)
.success();
}
#[test]
fn test_to_stdout_with_ibs_obs()
{
let output: Vec<_> = String::from("y\n")
.bytes()
.cycle()
.take(1024)
.collect();
let output = String::from_utf8(output).unwrap();
new_ucmd!()
.args(&[
"status=none",
"if=y-nl-1k.txt",
"ibs=521",
"obs=1031",
])
.run()
.no_stderr()
.stdout_is(output)
.success();
}
#[test]
fn test_ascii_10k_to_stdout()
{
let output = build_ascii_block(1024*1024);
// build_test_file!("ascii-10k.txt", &output);
let output = String::from_utf8(output).unwrap();
new_ucmd!()
.args(&[
"status=none",
"if=ascii-10k.txt",
])
.run()
.no_stderr()
.stdout_is(output)
.success();
}
#[test]
fn test_zeros_to_file()
{
let tname = "zero-256k";
let test_fn = format!("{}.txt", tname);
let tmp_fn = format!("TESTFILE-{}.tmp", &tname);
let (fix, mut ucmd) = at_and_ucmd!();
ucmd.args(&[
"status=none",
inf!(test_fn),
of!(tmp_fn),
])
.run()
.no_stderr()
.no_stdout()
.success();
cmp_file!(File::open(fixture_path!(&test_fn)).unwrap(),
fix.open(&tmp_fn));
}
#[test]
fn test_to_file_with_ibs_obs()
{
let tname = "zero-256k";
let test_fn = format!("{}.txt", tname);
let tmp_fn = format!("TESTFILE-{}.tmp", &tname);
let (fix, mut ucmd) = at_and_ucmd!();
ucmd.args(&[
"status=none",
inf!(test_fn),
of!(tmp_fn),
"ibs=222",
"obs=111",
])
.run()
.no_stderr()
.no_stdout()
.success();
cmp_file!(File::open(fixture_path!(&test_fn)).unwrap(),
fix.open(&tmp_fn));
}
#[test]
fn test_ascii_521k_to_file()
{
let tname = "ascii-521k";
let input = build_ascii_block(512*1024);
let tmp_fn = format!("TESTFILE-{}.tmp", &tname);
let (fix, mut ucmd) = at_and_ucmd!();
ucmd.args(&[
"status=none",
of!(tmp_fn),
])
.pipe_in(input.clone())
.run()
.no_stderr()
.no_stdout()
.success();
assert_eq!(512*1024, fix.metadata(&tmp_fn).len());
cmp_file!({ let mut input_f = tempfile().unwrap();
input_f.write(&input).unwrap();
input_f },
fix.open(&tmp_fn));
}
#[ignore]
#[cfg(unix)]
#[test]
fn test_ascii_5_gibi_to_file()
{
let tname = "ascii-5G";
let tmp_fn = format!("TESTFILE-{}.tmp", &tname);
let (fix, mut ucmd) = at_and_ucmd!();
ucmd.args(&[
"status=none",
"count=5G",
"iflag=count_bytes",
"if=/dev/zero",
of!(tmp_fn),
])
.run()
.no_stderr()
.no_stdout()
.success();
assert_eq!(5*1024*1024*1024, fix.metadata(&tmp_fn).len());
}
#[test]
fn test_self_transfer()
{
let fname = "self-transfer-256k.txt";
let (fix, mut ucmd) = at_and_ucmd!();
ucmd.args(&[
"status=none",
"conv=notrunc",
inf!(fname),
of!(fname),
]);
assert!(fix.file_exists(fname));
assert_eq!(256*1024, fix.metadata(fname).len());
ucmd.run()
.no_stdout()
.no_stderr()
.success();
assert!(fix.file_exists(fname));
assert_eq!(256*1024, fix.metadata(fname).len());
}
// conv=[ascii,ebcdic,ibm], conv=[ucase,lcase], conv=[block,unblock], conv=sync
// TODO: Move conv tests from unit test module

BIN
tests/fixtures/dd/ascii-10k.txt vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

0
tests/fixtures/dd/null.txt vendored Normal file
View file

BIN
tests/fixtures/dd/self-transfer-256k.txt vendored Normal file

Binary file not shown.

BIN
tests/fixtures/dd/seq-byte-values.test vendored Normal file

Binary file not shown.

View file

View file

View file

@ -0,0 +1 @@
abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd

View file

@ -0,0 +1 @@
abcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcdefabcd

View file

View file

512
tests/fixtures/dd/y-nl-1k.txt vendored Normal file
View file

@ -0,0 +1,512 @@
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y
y

BIN
tests/fixtures/dd/zero-256k.txt vendored Normal file

Binary file not shown.