diff --git a/src/uu/shuf/src/shuf.rs b/src/uu/shuf/src/shuf.rs index 7df7f1e44..091024ec4 100644 --- a/src/uu/shuf/src/shuf.rs +++ b/src/uu/shuf/src/shuf.rs @@ -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)) } diff --git a/tests/by-util/test_shuf.rs b/tests/by-util/test_shuf.rs index 91167b36e..335af7909 100644 --- a/tests/by-util/test_shuf.rs +++ b/tests/by-util/test_shuf.rs @@ -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 = 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::>() + .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 = 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::>() + ); +} + #[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!()