shuf: refuse multiple input ranges and multiple output files

This commit is contained in:
Ben Wiederhake 2024-02-16 21:14:56 +01:00
parent 69f23c2521
commit b091911aae
2 changed files with 77 additions and 3 deletions

View file

@ -120,7 +120,6 @@ pub fn uu_app() -> Command {
.version(crate_version!())
.override_usage(format_usage(USAGE))
.infer_long_args(true)
.args_override_self(true)
.arg(
Arg::new(options::ECHO)
.short('e')
@ -168,14 +167,16 @@ pub fn uu_app() -> Command {
.short('r')
.long(options::REPEAT)
.help("output lines can be repeated")
.action(ArgAction::SetTrue),
.action(ArgAction::SetTrue)
.overrides_with(options::REPEAT),
)
.arg(
Arg::new(options::ZERO_TERMINATED)
.short('z')
.long(options::ZERO_TERMINATED)
.help("line delimiter is NUL, not newline")
.action(ArgAction::SetTrue),
.action(ArgAction::SetTrue)
.overrides_with(options::ZERO_TERMINATED),
)
.arg(Arg::new(options::FILE).value_hint(clap::ValueHint::FilePath))
}

View file

@ -48,6 +48,22 @@ fn test_zero_termination() {
assert_eq!(result_seq, input_seq, "Output is not a permutation");
}
#[test]
fn test_zero_termination_multi() {
let input_seq = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let result = new_ucmd!().arg("-z").arg("-z").arg("-i1-10").succeeds();
result.no_stderr();
let mut result_seq: Vec<i32> = result
.stdout_str()
.split('\0')
.filter(|x| !x.is_empty())
.map(|x| x.parse().unwrap())
.collect();
result_seq.sort_unstable();
assert_eq!(result_seq, input_seq, "Output is not a permutation");
}
#[test]
fn test_empty_input() {
let result = new_ucmd!().pipe_in(vec![]).succeeds();
@ -235,6 +251,45 @@ fn test_repeat() {
);
}
#[test]
fn test_repeat_multi() {
let repeat_limit = 15000;
let input_seq = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let input = input_seq
.iter()
.map(ToString::to_string)
.collect::<Vec<String>>()
.join("\n");
let result = new_ucmd!()
.arg("-r")
.arg("-r") // The only difference to test_repeat()
.args(&["-n", &repeat_limit.to_string()])
.pipe_in(input.as_bytes())
.succeeds();
result.no_stderr();
let result_seq: Vec<i32> = result
.stdout_str()
.split('\n')
.filter(|x| !x.is_empty())
.map(|x| x.parse().unwrap())
.collect();
assert_eq!(
result_seq.len(),
repeat_limit,
"Output is not repeating forever"
);
assert!(
result_seq.iter().all(|x| input_seq.contains(x)),
"Output includes element not from input: {:?}",
result_seq
.iter()
.filter(|x| !input_seq.contains(x))
.collect::<Vec<&i32>>()
);
}
#[test]
fn test_file_input() {
let expected_seq = vec![11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
@ -292,6 +347,24 @@ fn test_shuf_invalid_input_range_three() {
.stderr_contains("invalid input range: 'b'");
}
#[test]
fn test_shuf_multiple_input_ranges() {
new_ucmd!()
.args(&["-i", "2-9", "-i", "2-9"])
.fails()
.stderr_contains("--input-range")
.stderr_contains("cannot be used multiple times");
}
#[test]
fn test_shuf_multiple_outputs() {
new_ucmd!()
.args(&["-o", "file_a", "-o", "file_b"])
.fails()
.stderr_contains("--output")
.stderr_contains("cannot be used multiple times");
}
#[test]
fn test_shuf_invalid_input_line_count() {
new_ucmd!()