Addresses code-quality issues from testsdiepraam and miDeb.

- Removes dd from feat_require_unix (keeps it in feat_common_core)
- Changes name of make_linux_iflags parameter from oflags to iflags.
- Removes roughed out SIGINFO impl.
- Renames plen -> target_len.
- Removes internal fn def for build_blocks and replaces with a call to
  chunks from std.
- Renames apply_ct to the more descriptive apply_conversion
- Replaces manual swap steps in perform_swab with call to swap from std.
- Replaces manual solution with chunks where appropriate (in Read, and Write impl).
- Renames xfer -> transfer (in local variable names).
- Improves documentation for dd_filout/dd_stdout issue.
- Removes commented debug_assert statements.
- Modifies ProdUpdate to contain ReadStat and WriteStat rather than
  copying their fields.
- Addresses verbose return in `Output<File>::new(...)`
- Resoves compiler warning when built as release when signal handler fails to
  register.
- Derives _Default_ trait on ReadStat.
- Adds comments for truncated lines in block unblock tests
- Removes `as u8` in block unblock tests.
- Removes unecessary `#[inline]`
- Delegates multiplier string parsing to uucore::parse_size.
- Renames 'unfailed' -> 'succeeded' for clairity.
- Removes #dead_code warnings. No clippy warnings on my local machine.
- Reworks signal handler to better accomodate platform-specific signals.
- Removes explicit references to "if" and "of" in dd.rs.
- Removes explicit references to "bs", "ibs", "cbs" and "status" in
  parseargs.rs.
- Removes `#[allow(deadcode)]` for OFlags, and IFlags.
- Removes spellchecker ignore from all dd files.
- Adds tests for 'traditional' and 'modern' CLI.
This commit is contained in:
Tyler
2021-07-21 17:25:10 -07:00
parent c3f9557581
commit 9d9267e08b
12 changed files with 377 additions and 418 deletions
-1
View File
@@ -153,7 +153,6 @@ feat_require_unix = [
"chmod",
"chown",
"chroot",
"dd",
"groups",
"hostid",
"id",
-2
View File
@@ -5,8 +5,6 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
/* cspell:disable */
// Note: 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.
+9 -35
View File
@@ -5,23 +5,18 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
/* cspell:disable */
use crate::conversion_tables::*;
use std::error::Error;
use std::time;
pub struct ProgUpdate {
pub reads_complete: u64,
pub reads_partial: u64,
pub writes_complete: u64,
pub writes_partial: u64,
pub bytes_total: u128,
pub records_truncated: u32,
pub read_stat: ReadStat,
pub write_stat: WriteStat,
pub duration: time::Duration,
}
#[derive(Clone, Copy, Default)]
pub struct ReadStat {
pub reads_complete: u64,
pub reads_partial: u64,
@@ -37,6 +32,7 @@ impl std::ops::AddAssign for ReadStat {
}
}
#[derive(Clone, Copy)]
pub struct WriteStat {
pub writes_complete: u64,
pub writes_partial: u64,
@@ -55,6 +51,7 @@ impl std::ops::AddAssign for WriteStat {
type Cbs = usize;
/// Stores all Conv Flags that apply to the input
#[derive(Debug, Default, PartialEq)]
pub struct IConvFlags {
pub ctable: Option<&'static ConversionTable>,
pub block: Option<Cbs>,
@@ -65,7 +62,7 @@ pub struct IConvFlags {
}
/// Stores all Conv Flags that apply to the output
#[derive(Debug, PartialEq)]
#[derive(Debug, Default, PartialEq)]
pub struct OConvFlags {
pub sparse: bool,
pub excl: bool,
@@ -76,32 +73,20 @@ pub struct OConvFlags {
}
/// Stores all Flags that apply to the input
#[derive(Debug, Default, PartialEq)]
pub struct IFlags {
#[allow(dead_code)]
pub cio: bool,
#[allow(dead_code)]
pub direct: bool,
#[allow(dead_code)]
pub directory: bool,
#[allow(dead_code)]
pub dsync: bool,
#[allow(dead_code)]
pub sync: bool,
#[allow(dead_code)]
pub nocache: bool,
#[allow(dead_code)]
pub nonblock: bool,
#[allow(dead_code)]
pub noatime: bool,
#[allow(dead_code)]
pub noctty: bool,
#[allow(dead_code)]
pub nofollow: bool,
#[allow(dead_code)]
pub nolinks: bool,
#[allow(dead_code)]
pub binary: bool,
#[allow(dead_code)]
pub text: bool,
pub fullblock: bool,
pub count_bytes: bool,
@@ -109,33 +94,21 @@ pub struct IFlags {
}
/// Stores all Flags that apply to the output
#[derive(Debug, Default, PartialEq)]
pub struct OFlags {
pub append: bool,
#[allow(dead_code)]
pub cio: bool,
#[allow(dead_code)]
pub direct: bool,
#[allow(dead_code)]
pub directory: bool,
#[allow(dead_code)]
pub dsync: bool,
#[allow(dead_code)]
pub sync: bool,
#[allow(dead_code)]
pub nocache: bool,
#[allow(dead_code)]
pub nonblock: bool,
#[allow(dead_code)]
pub noatime: bool,
#[allow(dead_code)]
pub noctty: bool,
#[allow(dead_code)]
pub nofollow: bool,
#[allow(dead_code)]
pub nolinks: bool,
#[allow(dead_code)]
pub binary: bool,
#[allow(dead_code)]
pub text: bool,
pub seek_bytes: bool,
}
@@ -153,6 +126,7 @@ pub enum StatusLevel {
/// Defaults to Reads(N)
/// if iflag=count_bytes
/// then becomes Bytes(N)
#[derive(Debug, PartialEq)]
pub enum CountType {
Reads(usize),
Bytes(usize),
+123 -228
View File
File diff suppressed because it is too large Load Diff
@@ -1,20 +1,7 @@
/* cspell:disable */
use super::*;
const NL: u8 = '\n' as u8;
const SPACE: u8 = ' ' as u8;
macro_rules! rs (
() =>
{
ReadStat {
reads_complete: 0,
reads_partial: 0,
records_truncated: 0,
}
};
);
const NL: u8 = b'\n';
const SPACE: u8 = b' ';
macro_rules! make_block_test (
( $test_id:ident, $test_name:expr, $src:expr, $block:expr, $spec:expr ) =>
@@ -25,7 +12,7 @@ macro_rules! make_block_test (
src: $src,
non_ascii: false,
ibs: 512,
xfer_stats: None,
print_level: None,
count: None,
cflags: IConvFlags {
ctable: None,
@@ -57,7 +44,7 @@ macro_rules! make_unblock_test (
src: $src,
non_ascii: false,
ibs: 512,
xfer_stats: None,
print_level: None,
count: None,
cflags: IConvFlags {
ctable: None,
@@ -82,7 +69,7 @@ macro_rules! make_unblock_test (
#[test]
fn block_test_no_nl() {
let mut rs = rs!();
let mut rs = ReadStat::default();
let buf = vec![0u8, 1u8, 2u8, 3u8];
let res = block(buf, 4, &mut rs);
@@ -91,7 +78,7 @@ fn block_test_no_nl() {
#[test]
fn block_test_no_nl_short_record() {
let mut rs = rs!();
let mut rs = ReadStat::default();
let buf = vec![0u8, 1u8, 2u8, 3u8];
let res = block(buf, 8, &mut rs);
@@ -103,17 +90,18 @@ fn block_test_no_nl_short_record() {
#[test]
fn block_test_no_nl_trunc() {
let mut rs = rs!();
let mut rs = ReadStat::default();
let buf = vec![0u8, 1u8, 2u8, 3u8, 4u8];
let res = block(buf, 4, &mut rs);
// Commented section should be truncated and appear for reference only.
assert_eq!(res, vec![vec![0u8, 1u8, 2u8, 3u8 /*, 4u8*/],]);
assert_eq!(rs.records_truncated, 1);
}
#[test]
fn block_test_nl_gt_cbs_trunc() {
let mut rs = rs!();
let mut rs = ReadStat::default();
let buf = vec![
0u8, 1u8, 2u8, 3u8, 4u8, NL, 0u8, 1u8, 2u8, 3u8, 4u8, NL, 5u8, 6u8, 7u8, 8u8,
];
@@ -122,6 +110,7 @@ fn block_test_nl_gt_cbs_trunc() {
assert_eq!(
res,
vec![
// Commented lines should be truncated and appear for reference only.
vec![0u8, 1u8, 2u8, 3u8],
// vec![4u8, SPACE, SPACE, SPACE],
vec![0u8, 1u8, 2u8, 3u8],
@@ -134,7 +123,7 @@ fn block_test_nl_gt_cbs_trunc() {
#[test]
fn block_test_surrounded_nl() {
let mut rs = rs!();
let mut rs = ReadStat::default();
let buf = vec![0u8, 1u8, 2u8, 3u8, NL, 4u8, 5u8, 6u8, 7u8, 8u8];
let res = block(buf, 8, &mut rs);
@@ -149,7 +138,7 @@ fn block_test_surrounded_nl() {
#[test]
fn block_test_multiple_nl_same_cbs_block() {
let mut rs = rs!();
let mut rs = ReadStat::default();
let buf = vec![0u8, 1u8, 2u8, 3u8, NL, 4u8, NL, 5u8, 6u8, 7u8, 8u8, 9u8];
let res = block(buf, 8, &mut rs);
@@ -165,7 +154,7 @@ fn block_test_multiple_nl_same_cbs_block() {
#[test]
fn block_test_multiple_nl_diff_cbs_block() {
let mut rs = rs!();
let mut rs = ReadStat::default();
let buf = vec![0u8, 1u8, 2u8, 3u8, NL, 4u8, 5u8, 6u8, 7u8, NL, 8u8, 9u8];
let res = block(buf, 8, &mut rs);
@@ -181,7 +170,7 @@ fn block_test_multiple_nl_diff_cbs_block() {
#[test]
fn block_test_end_nl_diff_cbs_block() {
let mut rs = rs!();
let mut rs = ReadStat::default();
let buf = vec![0u8, 1u8, 2u8, 3u8, NL];
let res = block(buf, 4, &mut rs);
@@ -190,7 +179,7 @@ fn block_test_end_nl_diff_cbs_block() {
#[test]
fn block_test_end_nl_same_cbs_block() {
let mut rs = rs!();
let mut rs = ReadStat::default();
let buf = vec![0u8, 1u8, 2u8, NL];
let res = block(buf, 4, &mut rs);
@@ -199,7 +188,7 @@ fn block_test_end_nl_same_cbs_block() {
#[test]
fn block_test_double_end_nl() {
let mut rs = rs!();
let mut rs = ReadStat::default();
let buf = vec![0u8, 1u8, 2u8, NL, NL];
let res = block(buf, 4, &mut rs);
@@ -211,7 +200,7 @@ fn block_test_double_end_nl() {
#[test]
fn block_test_start_nl() {
let mut rs = rs!();
let mut rs = ReadStat::default();
let buf = vec![NL, 0u8, 1u8, 2u8, 3u8];
let res = block(buf, 4, &mut rs);
@@ -223,7 +212,7 @@ fn block_test_start_nl() {
#[test]
fn block_test_double_surrounded_nl_no_trunc() {
let mut rs = rs!();
let mut rs = ReadStat::default();
let buf = vec![0u8, 1u8, 2u8, 3u8, NL, NL, 4u8, 5u8, 6u8, 7u8];
let res = block(buf, 8, &mut rs);
@@ -239,13 +228,14 @@ fn block_test_double_surrounded_nl_no_trunc() {
#[test]
fn block_test_double_surrounded_nl_double_trunc() {
let mut rs = rs!();
let mut rs = ReadStat::default();
let buf = vec![0u8, 1u8, 2u8, 3u8, NL, NL, 4u8, 5u8, 6u8, 7u8, 8u8];
let res = block(buf, 4, &mut rs);
assert_eq!(
res,
vec![
// Commented section should be truncated and appear for reference only.
vec![0u8, 1u8, 2u8, 3u8],
vec![SPACE, SPACE, SPACE, SPACE],
vec![4u8, 5u8, 6u8, 7u8 /*, 8u8*/],
@@ -1,5 +1,3 @@
/* cspell:disable */
use super::*;
macro_rules! make_sync_test (
@@ -11,7 +9,7 @@ macro_rules! make_sync_test (
src: $src,
non_ascii: false,
ibs: $ibs,
xfer_stats: None,
print_level: None,
count: None,
cflags: IConvFlags {
ctable: None,
@@ -1,5 +1,3 @@
/* cspell:disable */
use super::*;
macro_rules! make_conv_test (
@@ -11,7 +9,7 @@ macro_rules! make_conv_test (
src: $src,
non_ascii: false,
ibs: 512,
xfer_stats: None,
print_level: None,
count: None,
cflags: icf!($ctable),
iflags: DEFAULT_IFLAGS,
@@ -36,7 +34,7 @@ macro_rules! make_icf_test (
src: $src,
non_ascii: false,
ibs: 512,
xfer_stats: None,
print_level: None,
count: None,
cflags: $icf,
iflags: DEFAULT_IFLAGS,
@@ -141,7 +139,7 @@ fn all_valid_ascii_ebcdic_ascii_roundtrip_conv_test() {
.unwrap(),
non_ascii: false,
ibs: 128,
xfer_stats: None,
print_level: None,
count: None,
cflags: icf!(Some(&ASCII_TO_EBCDIC)),
iflags: DEFAULT_IFLAGS,
@@ -163,7 +161,7 @@ fn all_valid_ascii_ebcdic_ascii_roundtrip_conv_test() {
src: File::open(&tmp_fname_ae).unwrap(),
non_ascii: false,
ibs: 256,
xfer_stats: None,
print_level: None,
count: None,
cflags: icf!(Some(&EBCDIC_TO_ASCII)),
iflags: DEFAULT_IFLAGS,
+1 -21
View File
@@ -1,5 +1,3 @@
/* cspell:disable */
use super::*;
mod block_unblock_tests;
@@ -39,24 +37,6 @@ const DEFAULT_IFLAGS: IFlags = IFlags {
skip_bytes: false,
};
// const DEFAULT_OFLAGS: OFlags = OFlags {
// append: false,
// 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,
// seek_bytes: false,
// };
struct LazyReader<R: Read> {
src: R,
}
@@ -102,7 +82,7 @@ macro_rules! make_spec_test (
src: $src,
non_ascii: false,
ibs: 512,
xfer_stats: None,
print_level: None,
count: None,
cflags: icf!(),
iflags: DEFAULT_IFLAGS,
+9 -11
View File
@@ -1,5 +1,3 @@
/* cspell:disable */
use super::*;
const DST_PLACEHOLDER: Vec<u8> = Vec::new();
@@ -52,7 +50,7 @@ make_io_test!(
src: File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap(),
non_ascii: false,
ibs: 521,
xfer_stats: None,
print_level: None,
count: None,
cflags: icf!(),
iflags: DEFAULT_IFLAGS,
@@ -72,7 +70,7 @@ make_io_test!(
src: File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap(),
non_ascii: false,
ibs: 1031,
xfer_stats: None,
print_level: None,
count: None,
cflags: icf!(),
iflags: DEFAULT_IFLAGS,
@@ -92,7 +90,7 @@ make_io_test!(
src: File::open("./test-resources/deadbeef-18d99661a1de1fc9af21b0ec2cd67ba3.test").unwrap(),
non_ascii: false,
ibs: 1024,
xfer_stats: None,
print_level: None,
count: Some(CountType::Reads(32)),
cflags: icf!(),
iflags: DEFAULT_IFLAGS,
@@ -112,7 +110,7 @@ make_io_test!(
src: File::open("./test-resources/deadbeef-18d99661a1de1fc9af21b0ec2cd67ba3.test").unwrap(),
non_ascii: false,
ibs: 531,
xfer_stats: None,
print_level: None,
count: Some(CountType::Bytes(32 * 1024)),
cflags: icf!(),
iflags: DEFAULT_IFLAGS,
@@ -132,7 +130,7 @@ make_io_test!(
src: File::open("./test-resources/deadbeef-18d99661a1de1fc9af21b0ec2cd67ba3.test").unwrap(),
non_ascii: false,
ibs: 1024,
xfer_stats: None,
print_level: None,
count: Some(CountType::Reads(16)),
cflags: icf!(),
iflags: DEFAULT_IFLAGS,
@@ -152,7 +150,7 @@ make_io_test!(
src: File::open("./test-resources/deadbeef-18d99661a1de1fc9af21b0ec2cd67ba3.test").unwrap(),
non_ascii: false,
ibs: 531,
xfer_stats: None,
print_level: None,
count: Some(CountType::Bytes(12345)),
cflags: icf!(),
iflags: DEFAULT_IFLAGS,
@@ -172,7 +170,7 @@ make_io_test!(
src: File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap(),
non_ascii: false,
ibs: 1024,
xfer_stats: None,
print_level: None,
count: Some(CountType::Reads(32)),
cflags: icf!(),
iflags: DEFAULT_IFLAGS,
@@ -192,7 +190,7 @@ make_io_test!(
src: File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap(),
non_ascii: false,
ibs: 521,
xfer_stats: None,
print_level: None,
count: Some(CountType::Bytes(32 * 1024)),
cflags: icf!(),
iflags: DEFAULT_IFLAGS,
@@ -215,7 +213,7 @@ make_io_test!(
},
non_ascii: false,
ibs: 521,
xfer_stats: None,
print_level: None,
count: None,
cflags: icf!(),
iflags: IFlags {
+29 -56
View File
@@ -5,8 +5,6 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
/* cspell:disable */
#[cfg(test)]
mod unit_tests;
@@ -24,9 +22,8 @@ pub enum ParseError {
MultipleExclNoCreat,
FlagNoMatch(String),
ConvFlagNoMatch(String),
NoMatchingMultiplier(String),
ByteStringContainsNoValue(String),
MultiplierStringWouldOverflow(String),
MultiplierStringParseFailure(String),
MultiplierStringOverflow(String),
BlockUnblockWithoutCBS,
StatusLevelNotRecognized(String),
Unimplemented(String),
@@ -56,13 +53,10 @@ impl std::fmt::Display for ParseError {
Self::ConvFlagNoMatch(arg) => {
write!(f, "Unrecognized conv=CONV -> {}", arg)
}
Self::NoMatchingMultiplier(arg) => {
Self::MultiplierStringParseFailure(arg) => {
write!(f, "Unrecognized byte multiplier -> {}", arg)
}
Self::ByteStringContainsNoValue(arg) => {
write!(f, "Unrecognized byte value -> {}", arg)
}
Self::MultiplierStringWouldOverflow(arg) => {
Self::MultiplierStringOverflow(arg) => {
write!(
f,
"Multiplier string would overflow on current system -> {}",
@@ -302,61 +296,40 @@ impl std::str::FromStr for StatusLevel {
}
}
fn parse_multiplier(s: &'_ str) -> Result<usize, ParseError> {
let mult: u128 = match s {
"c" => 1,
"w" => 2,
"b" => 512,
"kB" => 1000,
"K" | "KiB" => 1024,
"MB" => 1000 * 1000,
"M" | "MiB" => 1024 * 1024,
"GB" => 1000 * 1000 * 1000,
"G" | "GiB" => 1024 * 1024 * 1024,
"TB" => 1000 * 1000 * 1000 * 1000,
"T" | "TiB" => 1024 * 1024 * 1024 * 1024,
"PB" => 1000 * 1000 * 1000 * 1000 * 1000,
"P" | "PiB" => 1024 * 1024 * 1024 * 1024 * 1024,
"EB" => 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
"E" | "EiB" => 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
"ZB" => 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
"Z" | "ZiB" => 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
"YB" => 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000,
"Y" | "YiB" => 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024,
_ => return Err(ParseError::NoMatchingMultiplier(s.to_string())),
};
mult.try_into()
.map_err(|_e| ParseError::MultiplierStringWouldOverflow(s.to_string()))
}
/// Parse bytes using str::parse, then map error if needed.
fn parse_bytes_only(s: &str) -> Result<usize, ParseError> {
match s.parse() {
Ok(bytes) => Ok(bytes),
Err(_) => Err(ParseError::ByteStringContainsNoValue(s.to_string())),
}
s.parse()
.map_err(|_| ParseError::MultiplierStringParseFailure(s.to_string()))
}
/// Parse byte and multiplier like 512, 5KiB, or 1G.
/// Uses uucore::parse_size, and adds the 'w' and 'c' suffixes which are mentioned
/// in dd's info page.
fn parse_bytes_with_opt_multiplier(s: &str) -> Result<usize, ParseError> {
match s.find(char::is_alphabetic) {
Some(idx) => {
let base = parse_bytes_only(&s[..idx])?;
let mult = parse_multiplier(&s[idx..])?;
if let Some(idx) = s.rfind('c') {
parse_bytes_only(&s[..idx])
} else if let Some(idx) = s.rfind('w') {
let partial = parse_bytes_only(&s[..idx])?;
if let Some(bytes) = base.checked_mul(mult) {
Ok(bytes)
} else {
Err(ParseError::MultiplierStringWouldOverflow(s.to_string()))
partial
.checked_mul(2)
.ok_or_else(|| ParseError::MultiplierStringOverflow(s.to_string()))
} else {
uucore::parse_size::parse_size(s).map_err(|e| match e {
uucore::parse_size::ParseSizeError::ParseFailure(s) => {
ParseError::MultiplierStringParseFailure(s)
}
}
_ => parse_bytes_only(s),
uucore::parse_size::ParseSizeError::SizeTooBig(s) => {
ParseError::MultiplierStringOverflow(s)
}
})
}
}
pub fn parse_ibs(matches: &Matches) -> Result<usize, ParseError> {
if let Some(mixed_str) = matches.value_of("bs") {
if let Some(mixed_str) = matches.value_of(options::BS) {
parse_bytes_with_opt_multiplier(mixed_str)
} else if let Some(mixed_str) = matches.value_of("ibs") {
} else if let Some(mixed_str) = matches.value_of(options::IBS) {
parse_bytes_with_opt_multiplier(mixed_str)
} else {
Ok(512)
@@ -364,7 +337,7 @@ pub fn parse_ibs(matches: &Matches) -> Result<usize, ParseError> {
}
fn parse_cbs(matches: &Matches) -> Result<Option<usize>, ParseError> {
if let Some(s) = matches.value_of("cbs") {
if let Some(s) = matches.value_of(options::CBS) {
let bytes = parse_bytes_with_opt_multiplier(s)?;
Ok(Some(bytes))
} else {
@@ -373,7 +346,7 @@ fn parse_cbs(matches: &Matches) -> Result<Option<usize>, ParseError> {
}
pub fn parse_status_level(matches: &Matches) -> Result<Option<StatusLevel>, ParseError> {
match matches.value_of("status") {
match matches.value_of(options::STATUS) {
Some(s) => {
let st = s.parse()?;
Ok(Some(st))
+181 -23
View File
@@ -1,5 +1,3 @@
/* cspell:disable */
use super::*;
use crate::StatusLevel;
@@ -7,7 +5,7 @@ use crate::StatusLevel;
#[cfg(not(target_os = "linux"))]
#[test]
fn unimplemented_flags_should_error_non_unix() {
let mut unfailed = Vec::new();
let mut succeeded = Vec::new();
// The following flags are only implemented in linux
for flag in vec![
@@ -28,26 +26,26 @@ fn unimplemented_flags_should_error_non_unix() {
let matches = uu_app().get_matches_from_safe(args).unwrap();
match parse_iflags(&matches) {
Ok(_) => unfailed.push(format!("iflag={}", flag)),
Ok(_) => succeeded.push(format!("iflag={}", flag)),
Err(_) => { /* expected behaviour :-) */ }
}
match parse_oflags(&matches) {
Ok(_) => unfailed.push(format!("oflag={}", flag)),
Ok(_) => succeeded.push(format!("oflag={}", flag)),
Err(_) => { /* expected behaviour :-) */ }
}
}
if !unfailed.is_empty() {
if !succeeded.is_empty() {
panic!(
"The following flags did not panic as expected: {:?}",
unfailed
succeeded
);
}
}
#[test]
fn unimplemented_flags_should_error() {
let mut unfailed = Vec::new();
let mut succeeded = Vec::new();
// The following flags are not implemented
for flag in vec!["cio", "nocache", "nolinks", "text", "binary"] {
@@ -59,19 +57,19 @@ fn unimplemented_flags_should_error() {
let matches = uu_app().get_matches_from_safe(args).unwrap();
match parse_iflags(&matches) {
Ok(_) => unfailed.push(format!("iflag={}", flag)),
Ok(_) => succeeded.push(format!("iflag={}", flag)),
Err(_) => { /* expected behaviour :-) */ }
}
match parse_oflags(&matches) {
Ok(_) => unfailed.push(format!("oflag={}", flag)),
Ok(_) => succeeded.push(format!("oflag={}", flag)),
Err(_) => { /* expected behaviour :-) */ }
}
}
if !unfailed.is_empty() {
if !succeeded.is_empty() {
panic!(
"The following flags did not panic as expected: {:?}",
unfailed
succeeded
);
}
}
@@ -105,6 +103,176 @@ fn test_status_level_none() {
assert_eq!(st, StatusLevel::None);
}
#[test]
fn test_all_top_level_args_no_leading_dashes_sep_by_equals() {
let args = vec![
String::from("dd"),
String::from("if=foo.file"),
String::from("of=bar.file"),
String::from("ibs=10"),
String::from("obs=10"),
String::from("cbs=1"),
String::from("bs=100"),
String::from("count=2"),
String::from("skip=2"),
String::from("seek=2"),
String::from("status=progress"),
String::from("conv=ascii,ucase"),
String::from("iflag=count_bytes,skip_bytes"),
String::from("oflag=append,seek_bytes"),
];
let args = args
.into_iter()
.fold(Vec::new(), append_dashes_if_not_present);
let matches = uu_app().get_matches_from_safe(args).unwrap();
assert_eq!(100, parse_ibs(&matches).unwrap());
assert_eq!(100, parse_obs(&matches).unwrap());
assert_eq!(1, parse_cbs(&matches).unwrap().unwrap());
assert_eq!(
CountType::Bytes(2),
parse_count(
&IFlags {
count_bytes: true,
..IFlags::default()
},
&matches
)
.unwrap()
.unwrap()
);
assert_eq!(
200,
parse_skip_amt(&100, &IFlags::default(), &matches)
.unwrap()
.unwrap()
);
assert_eq!(
200,
parse_seek_amt(&100, &OFlags::default(), &matches)
.unwrap()
.unwrap()
);
assert_eq!(
StatusLevel::Progress,
parse_status_level(&matches).unwrap().unwrap()
);
assert_eq!(
IConvFlags {
ctable: Some(&EBCDIC_TO_ASCII_LCASE_TO_UCASE),
..IConvFlags::default()
},
parse_conv_flag_input(&matches).unwrap()
);
assert_eq!(
OConvFlags::default(),
parse_conv_flag_output(&matches).unwrap()
);
assert_eq!(
IFlags {
count_bytes: true,
skip_bytes: true,
..IFlags::default()
},
parse_iflags(&matches).unwrap()
);
assert_eq!(
OFlags {
append: true,
seek_bytes: true,
..OFlags::default()
},
parse_oflags(&matches).unwrap()
);
}
#[ignore]
#[test]
// TODO: This should work, but Clap doesn't seem to understand it. Leaving it for now since the traditional dd if=foo.file works just fine.
fn test_all_top_level_args_leading_dashes_sep_by_spaces() {
let args = vec![
String::from("dd"),
String::from("--if foo.file"),
String::from("--of bar.file"),
String::from("--ibs 10"),
String::from("--obs 10"),
String::from("--cbs 1"),
String::from("--bs 100"),
String::from("--count 2"),
String::from("--skip 2"),
String::from("--seek 2"),
String::from("--status progress"),
String::from("--conv ascii,ucase"),
String::from("--iflag count_bytes,skip_bytes"),
String::from("--oflag append,seek_bytes"),
];
let args = args
.into_iter()
.fold(Vec::new(), append_dashes_if_not_present);
let matches = uu_app().get_matches_from_safe(args).unwrap();
assert_eq!(100, parse_ibs(&matches).unwrap());
assert_eq!(100, parse_obs(&matches).unwrap());
assert_eq!(1, parse_cbs(&matches).unwrap().unwrap());
assert_eq!(
CountType::Bytes(2),
parse_count(
&IFlags {
count_bytes: true,
..IFlags::default()
},
&matches
)
.unwrap()
.unwrap()
);
assert_eq!(
200,
parse_skip_amt(&100, &IFlags::default(), &matches)
.unwrap()
.unwrap()
);
assert_eq!(
200,
parse_seek_amt(&100, &OFlags::default(), &matches)
.unwrap()
.unwrap()
);
assert_eq!(
StatusLevel::Progress,
parse_status_level(&matches).unwrap().unwrap()
);
assert_eq!(
IConvFlags {
ctable: Some(&EBCDIC_TO_ASCII_LCASE_TO_UCASE),
..IConvFlags::default()
},
parse_conv_flag_input(&matches).unwrap()
);
assert_eq!(
OConvFlags::default(),
parse_conv_flag_output(&matches).unwrap()
);
assert_eq!(
IFlags {
count_bytes: true,
skip_bytes: true,
..IFlags::default()
},
parse_iflags(&matches).unwrap()
);
assert_eq!(
OFlags {
append: true,
seek_bytes: true,
..OFlags::default()
},
parse_oflags(&matches).unwrap()
);
}
#[test]
fn test_status_level_progress() {
let args = vec![
@@ -374,16 +542,6 @@ test_byte_parser!(
6 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024
);
#[test]
#[should_panic]
#[allow(non_snake_case)]
fn test_KB_multiplier_error() {
// KB is not valid (kB, K, and KiB are)
let bs_str = "2000KB";
parse_bytes_with_opt_multiplier(bs_str).unwrap();
}
#[test]
#[should_panic]
fn test_overflow_panic() {
@@ -395,7 +553,7 @@ fn test_overflow_panic() {
#[test]
#[should_panic]
fn test_neg_panic() {
let bs_str = format!("{}KiB", -1);
let bs_str = format!("{}", -1);
parse_bytes_with_opt_multiplier(&bs_str).unwrap();
}
-2
View File
@@ -1,5 +1,3 @@
/* cspell:disable */
use crate::common::util::*;
use std::fs::{File, OpenOptions};