1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-09-15 11:36:16 +00:00

Merge branch 'main' into fix-5327

This commit is contained in:
tommady 2023-10-04 16:06:48 +08:00 committed by GitHub
commit 879b4f363d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 1255 additions and 631 deletions

View file

@ -483,7 +483,8 @@ fn test_cp_arg_interactive_verbose() {
ucmd.args(&["-vi", "a", "b"])
.pipe_in("N\n")
.fails()
.stdout_is("skipped 'b'\n");
.stderr_is("cp: overwrite 'b'? ")
.no_stdout();
}
#[test]
@ -494,7 +495,8 @@ fn test_cp_arg_interactive_verbose_clobber() {
at.touch("b");
ucmd.args(&["-vin", "a", "b"])
.fails()
.stdout_is("skipped 'b'\n");
.stderr_is("cp: not replacing 'b'\n")
.no_stdout();
}
#[test]
@ -3466,3 +3468,19 @@ fn test_cp_only_source_no_target() {
panic!("Failure: stderr was \n{stderr_str}");
}
}
#[test]
fn test_cp_dest_no_permissions() {
let ts = TestScenario::new(util_name!());
let at = &ts.fixtures;
at.touch("valid.txt");
at.touch("invalid_perms.txt");
at.set_readonly("invalid_perms.txt");
ts.ucmd()
.args(&["valid.txt", "invalid_perms.txt"])
.fails()
.stderr_contains("invalid_perms.txt")
.stderr_contains("denied");
}

View file

@ -122,7 +122,7 @@ fn test_escape_no_further_output() {
new_ucmd!()
.args(&["-e", "a\\cb", "c"])
.succeeds()
.stdout_only("a\n");
.stdout_only("a");
}
#[test]
@ -236,3 +236,47 @@ fn test_hyphen_values_between() {
.success()
.stdout_is("dumdum dum dum dum -e dum\n");
}
#[test]
fn wrapping_octal() {
// Some odd behavior of GNU. Values of \0400 and greater do not fit in the
// u8 that we write to stdout. So we test that it wraps:
//
// We give it this input:
// \o501 = 1_0100_0001 (yes, **9** bits)
// This should be wrapped into:
// \o101 = 'A' = 0100_0001,
// because we only write a single character
new_ucmd!()
.arg("-e")
.arg("\\0501")
.succeeds()
.stdout_is("A\n");
}
#[test]
fn old_octal_syntax() {
new_ucmd!()
.arg("-e")
.arg("\\1foo")
.succeeds()
.stdout_is("\x01foo\n");
new_ucmd!()
.arg("-e")
.arg("\\43foo")
.succeeds()
.stdout_is("#foo\n");
new_ucmd!()
.arg("-e")
.arg("\\101 foo")
.succeeds()
.stdout_is("A foo\n");
new_ucmd!()
.arg("-e")
.arg("\\1011")
.succeeds()
.stdout_is("A1\n");
}

View file

@ -48,6 +48,17 @@ fn test_fmt_width_too_big() {
}
}
#[test]
fn test_fmt_invalid_width() {
for param in ["-w", "--width"] {
new_ucmd!()
.args(&["one-word-per-line.txt", param, "invalid"])
.fails()
.code_is(1)
.stderr_contains("invalid value 'invalid'");
}
}
#[ignore]
#[test]
fn test_fmt_goal() {
@ -70,6 +81,17 @@ fn test_fmt_goal_too_big() {
}
}
#[test]
fn test_fmt_invalid_goal() {
for param in ["-g", "--goal"] {
new_ucmd!()
.args(&["one-word-per-line.txt", param, "invalid"])
.fails()
.code_is(1)
.stderr_contains("invalid value 'invalid'");
}
}
#[test]
fn test_fmt_set_goal_not_contain_width() {
for param in ["-g", "--goal"] {

View file

@ -1928,6 +1928,35 @@ fn test_ls_recursive() {
result.stdout_contains("a\\b:\nb");
}
#[test]
fn test_ls_recursive_1() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.mkdir("x");
at.mkdir("y");
at.mkdir("a");
at.mkdir("b");
at.mkdir("c");
at.mkdir("a/1");
at.mkdir("a/2");
at.mkdir("a/3");
at.touch("f");
at.touch("a/1/I");
at.touch("a/1/II");
#[cfg(unix)]
let out = "a:\n1\n2\n3\n\na/1:\nI\nII\n\na/2:\n\na/3:\n\nb:\n\nc:\n";
#[cfg(windows)]
let out = "a:\n1\n2\n3\n\na\\1:\nI\nII\n\na\\2:\n\na\\3:\n\nb:\n\nc:\n";
scene
.ucmd()
.arg("-R1")
.arg("a")
.arg("b")
.arg("c")
.succeeds()
.stdout_is(out);
}
#[test]
fn test_ls_color() {
let scene = TestScenario::new(util_name!());

View file

@ -1323,7 +1323,7 @@ fn test_mv_interactive_error() {
}
#[test]
fn test_mv_info_self() {
fn test_mv_into_self() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let dir1 = "dir1";
@ -1350,7 +1350,7 @@ fn test_mv_arg_interactive_skipped() {
.ignore_stdin_write_error()
.fails()
.stderr_is("mv: overwrite 'b'? ")
.stdout_is("skipped 'b'\n");
.no_stdout();
}
#[test]
@ -1360,7 +1360,8 @@ fn test_mv_arg_interactive_skipped_vin() {
at.touch("b");
ucmd.args(&["-vin", "a", "b"])
.fails()
.stdout_is("skipped 'b'\n");
.stderr_is("mv: not replacing 'b'\n")
.no_stdout();
}
#[test]

View file

@ -2,7 +2,8 @@
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// spell-checker:ignore binvalid finvalid hinvalid iinvalid linvalid ninvalid vinvalid winvalid
//
// spell-checker:ignore binvalid finvalid hinvalid iinvalid linvalid nabcabc nabcabcabc ninvalid vinvalid winvalid
use crate::common::util::TestScenario;
#[test]
@ -537,3 +538,99 @@ fn test_line_number_overflow() {
.stdout_is(format!("{}\ta\n", i64::MIN))
.stderr_is("nl: line number overflow\n");
}
#[test]
fn test_line_number_no_overflow() {
new_ucmd!()
.arg(format!("--starting-line-number={}", i64::MAX))
.pipe_in("a\n\\:\\:\nb")
.succeeds()
.stdout_is(format!("{0}\ta\n\n{0}\tb\n", i64::MAX));
new_ucmd!()
.arg(format!("--starting-line-number={}", i64::MIN))
.arg("--line-increment=-1")
.pipe_in("a\n\\:\\:\nb")
.succeeds()
.stdout_is(format!("{0}\ta\n\n{0}\tb\n", i64::MIN));
}
#[test]
fn test_section_delimiter() {
for arg in ["-dabc", "--section-delimiter=abc"] {
new_ucmd!()
.arg(arg)
.pipe_in("a\nabcabcabc\nb") // header section
.succeeds()
.stdout_is(" 1\ta\n\n b\n");
new_ucmd!()
.arg(arg)
.pipe_in("a\nabcabc\nb") // body section
.succeeds()
.stdout_is(" 1\ta\n\n 1\tb\n");
new_ucmd!()
.arg(arg)
.pipe_in("a\nabc\nb") // footer section
.succeeds()
.stdout_is(" 1\ta\n\n b\n");
}
}
#[test]
fn test_one_char_section_delimiter_expansion() {
for arg in ["-da", "--section-delimiter=a"] {
new_ucmd!()
.arg(arg)
.pipe_in("a\na:a:a:\nb") // header section
.succeeds()
.stdout_is(" 1\ta\n\n b\n");
new_ucmd!()
.arg(arg)
.pipe_in("a\na:a:\nb") // body section
.succeeds()
.stdout_is(" 1\ta\n\n 1\tb\n");
new_ucmd!()
.arg(arg)
.pipe_in("a\na:\nb") // footer section
.succeeds()
.stdout_is(" 1\ta\n\n b\n");
}
}
#[test]
fn test_non_ascii_one_char_section_delimiter() {
for arg in ["-dä", "--section-delimiter=ä"] {
new_ucmd!()
.arg(arg)
.pipe_in("a\näää\nb") // header section
.succeeds()
.stdout_is(" 1\ta\n\n b\n");
new_ucmd!()
.arg(arg)
.pipe_in("a\nää\nb") // body section
.succeeds()
.stdout_is(" 1\ta\n\n 1\tb\n");
new_ucmd!()
.arg(arg)
.pipe_in("a\nä\nb") // footer section
.succeeds()
.stdout_is(" 1\ta\n\n b\n");
}
}
#[test]
fn test_empty_section_delimiter() {
for arg in ["-d ''", "--section-delimiter=''"] {
new_ucmd!()
.arg(arg)
.pipe_in("a\n\nb")
.succeeds()
.stdout_is(" 1\ta\n \n 2\tb\n");
}
}

View file

@ -623,11 +623,21 @@ fn test_neg_inf() {
run(&["--", "-inf", "0"], b"-inf\n-inf\n-inf\n");
}
#[test]
fn test_neg_infinity() {
run(&["--", "-infinity", "0"], b"-inf\n-inf\n-inf\n");
}
#[test]
fn test_inf() {
run(&["inf"], b"1\n2\n3\n");
}
#[test]
fn test_infinity() {
run(&["infinity"], b"1\n2\n3\n");
}
#[test]
fn test_inf_width() {
run(

View file

@ -1483,3 +1483,242 @@ fn test_split_non_utf8_argument_windows() {
.fails()
.stderr_contains("error: invalid UTF-8 was detected in one or more arguments");
}
// Test '--separator' / '-t' option following GNU tests example
// test separators: '\n' , '\0' , ';'
// test with '--lines=2' , '--line-bytes=4' , '--number=l/3' , '--number=r/3' , '--number=l/1/3' , '--number=r/1/3'
#[test]
fn test_split_separator_nl_lines() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["--lines=2", "-t", "\n"])
.pipe_in("1\n2\n3\n4\n5\n")
.succeeds();
assert_eq!(file_read(&at, "xaa"), "1\n2\n");
assert_eq!(file_read(&at, "xab"), "3\n4\n");
assert_eq!(file_read(&at, "xac"), "5\n");
assert!(!at.plus("xad").exists());
}
#[test]
fn test_split_separator_nl_line_bytes() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["--line-bytes=4", "-t", "\n"])
.pipe_in("1\n2\n3\n4\n5\n")
.succeeds();
assert_eq!(file_read(&at, "xaa"), "1\n2\n");
assert_eq!(file_read(&at, "xab"), "3\n4\n");
assert_eq!(file_read(&at, "xac"), "5\n");
assert!(!at.plus("xad").exists());
}
#[test]
fn test_split_separator_nl_number_l() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["--number=l/3", "--separator=\n", "fivelines.txt"])
.succeeds();
assert_eq!(file_read(&at, "xaa"), "1\n2\n");
assert_eq!(file_read(&at, "xab"), "3\n4\n");
assert_eq!(file_read(&at, "xac"), "5\n");
assert!(!at.plus("xad").exists());
}
#[test]
fn test_split_separator_nl_number_r() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["--number=r/3", "--separator", "\n", "fivelines.txt"])
.succeeds();
assert_eq!(file_read(&at, "xaa"), "1\n4\n");
assert_eq!(file_read(&at, "xab"), "2\n5\n");
assert_eq!(file_read(&at, "xac"), "3\n");
assert!(!at.plus("xad").exists());
}
#[test]
fn test_split_separator_nul_lines() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["--lines=2", "-t", "\\0", "separator_nul.txt"])
.succeeds();
assert_eq!(file_read(&at, "xaa"), "1\02\0");
assert_eq!(file_read(&at, "xab"), "3\04\0");
assert_eq!(file_read(&at, "xac"), "5\0");
assert!(!at.plus("xad").exists());
}
#[test]
fn test_split_separator_nul_line_bytes() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["--line-bytes=4", "-t", "\\0", "separator_nul.txt"])
.succeeds();
assert_eq!(file_read(&at, "xaa"), "1\02\0");
assert_eq!(file_read(&at, "xab"), "3\04\0");
assert_eq!(file_read(&at, "xac"), "5\0");
assert!(!at.plus("xad").exists());
}
#[test]
fn test_split_separator_nul_number_l() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["--number=l/3", "--separator=\\0", "separator_nul.txt"])
.succeeds();
assert_eq!(file_read(&at, "xaa"), "1\02\0");
assert_eq!(file_read(&at, "xab"), "3\04\0");
assert_eq!(file_read(&at, "xac"), "5\0");
assert!(!at.plus("xad").exists());
}
#[test]
fn test_split_separator_nul_number_r() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["--number=r/3", "--separator=\\0", "separator_nul.txt"])
.succeeds();
assert_eq!(file_read(&at, "xaa"), "1\04\0");
assert_eq!(file_read(&at, "xab"), "2\05\0");
assert_eq!(file_read(&at, "xac"), "3\0");
assert!(!at.plus("xad").exists());
}
#[test]
fn test_split_separator_semicolon_lines() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["--lines=2", "-t", ";", "separator_semicolon.txt"])
.succeeds();
assert_eq!(file_read(&at, "xaa"), "1;2;");
assert_eq!(file_read(&at, "xab"), "3;4;");
assert_eq!(file_read(&at, "xac"), "5;");
assert!(!at.plus("xad").exists());
}
#[test]
fn test_split_separator_semicolon_line_bytes() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["--line-bytes=4", "-t", ";", "separator_semicolon.txt"])
.succeeds();
assert_eq!(file_read(&at, "xaa"), "1;2;");
assert_eq!(file_read(&at, "xab"), "3;4;");
assert_eq!(file_read(&at, "xac"), "5;");
assert!(!at.plus("xad").exists());
}
#[test]
fn test_split_separator_semicolon_number_l() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["--number=l/3", "--separator=;", "separator_semicolon.txt"])
.succeeds();
assert_eq!(file_read(&at, "xaa"), "1;2;");
assert_eq!(file_read(&at, "xab"), "3;4;");
assert_eq!(file_read(&at, "xac"), "5;");
assert!(!at.plus("xad").exists());
}
#[test]
fn test_split_separator_semicolon_number_r() {
let (at, mut ucmd) = at_and_ucmd!();
ucmd.args(&["--number=r/3", "--separator=;", "separator_semicolon.txt"])
.succeeds();
assert_eq!(file_read(&at, "xaa"), "1;4;");
assert_eq!(file_read(&at, "xab"), "2;5;");
assert_eq!(file_read(&at, "xac"), "3;");
assert!(!at.plus("xad").exists());
}
#[test]
fn test_split_separator_semicolon_number_kth_l() {
new_ucmd!()
.args(&[
"--number=l/1/3",
"--separator",
";",
"separator_semicolon.txt",
])
.succeeds()
.stdout_only("1;2;");
}
#[test]
fn test_split_separator_semicolon_number_kth_r() {
new_ucmd!()
.args(&[
"--number=r/1/3",
"--separator",
";",
"separator_semicolon.txt",
])
.succeeds()
.stdout_only("1;4;");
}
// Test error edge cases for separator option
#[test]
fn test_split_separator_no_value() {
new_ucmd!()
.args(&["-t"])
.ignore_stdin_write_error()
.pipe_in("a\n")
.fails()
.stderr_contains(
"error: a value is required for '--separator <SEP>' but none was supplied",
);
}
#[test]
fn test_split_separator_invalid_usage() {
let scene = TestScenario::new(util_name!());
scene
.ucmd()
.args(&["--separator=xx"])
.ignore_stdin_write_error()
.pipe_in("a\n")
.fails()
.no_stdout()
.stderr_contains("split: multi-character separator 'xx'");
scene
.ucmd()
.args(&["-ta", "-tb"])
.ignore_stdin_write_error()
.pipe_in("a\n")
.fails()
.no_stdout()
.stderr_contains("split: multiple separator characters specified");
scene
.ucmd()
.args(&["-t'\n'", "-tb"])
.ignore_stdin_write_error()
.pipe_in("a\n")
.fails()
.no_stdout()
.stderr_contains("split: multiple separator characters specified");
}
// Test using same separator multiple times
#[test]
fn test_split_separator_same_multiple() {
let scene = TestScenario::new(util_name!());
scene
.ucmd()
.args(&["--separator=:", "--separator=:", "fivelines.txt"])
.succeeds();
scene
.ucmd()
.args(&["-t:", "--separator=:", "fivelines.txt"])
.succeeds();
scene
.ucmd()
.args(&["-t", ":", "-t", ":", "fivelines.txt"])
.succeeds();
scene
.ucmd()
.args(&["-t:", "-t:", "-t,", "fivelines.txt"])
.fails();
}

View file

@ -844,3 +844,15 @@ fn test_touch_dash() {
ucmd.args(&["-h", "-"]).succeeds().no_stderr().no_stdout();
}
#[test]
// Chrono panics for now
#[ignore]
fn test_touch_invalid_date_format() {
let (_at, mut ucmd) = at_and_ucmd!();
let file = "test_touch_invalid_date_format";
ucmd.args(&["-m", "-t", "+1000000000000 years", file])
.fails()
.stderr_contains("touch: invalid date format +1000000000000 years");
}

BIN
tests/fixtures/split/separator_nul.txt vendored Normal file

Binary file not shown.

View file

@ -0,0 +1 @@
1;2;3;4;5;