mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-09-16 19:56:17 +00:00
Merge branch 'master' into ls_selinux
This commit is contained in:
commit
4dc6536bb9
114 changed files with 1238 additions and 944 deletions
|
@ -139,6 +139,14 @@ fn test_chown_only_owner_colon() {
|
|||
.succeeds()
|
||||
.stderr_contains(&"retained as");
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg(format!("{}.", user_name))
|
||||
.arg("--verbose")
|
||||
.arg(file1)
|
||||
.succeeds()
|
||||
.stderr_contains(&"retained as");
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("root:")
|
||||
|
@ -180,6 +188,14 @@ fn test_chown_only_colon() {
|
|||
.arg(file1)
|
||||
.fails()
|
||||
.stderr_contains(&"invalid group: '::'");
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("..")
|
||||
.arg("--verbose")
|
||||
.arg(file1)
|
||||
.fails()
|
||||
.stderr_contains(&"invalid group: '..'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -232,6 +248,22 @@ fn test_chown_owner_group() {
|
|||
}
|
||||
result.stderr_contains(&"retained as");
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("root:root:root")
|
||||
.arg("--verbose")
|
||||
.arg(file1)
|
||||
.fails()
|
||||
.stderr_contains(&"invalid group");
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("root.root.root")
|
||||
.arg("--verbose")
|
||||
.arg(file1)
|
||||
.fails()
|
||||
.stderr_contains(&"invalid group");
|
||||
|
||||
// TODO: on macos group name is not recognized correctly: "chown: invalid group: 'root:root'
|
||||
#[cfg(any(windows, all(unix, not(target_os = "macos"))))]
|
||||
scene
|
||||
|
@ -243,6 +275,67 @@ fn test_chown_owner_group() {
|
|||
.stderr_contains(&"failed to change");
|
||||
}
|
||||
|
||||
#[test]
|
||||
// FixME: Fails on freebsd because of chown: invalid group: 'root:root'
|
||||
#[cfg(not(target_os = "freebsd"))]
|
||||
fn test_chown_various_input() {
|
||||
// test chown username:group file.txt
|
||||
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let result = scene.cmd("whoami").run();
|
||||
if skipping_test_is_okay(&result, "whoami: cannot find name for user ID") {
|
||||
return;
|
||||
}
|
||||
|
||||
let user_name = String::from(result.stdout_str().trim());
|
||||
assert!(!user_name.is_empty());
|
||||
|
||||
let file1 = "test_chown_file1";
|
||||
at.touch(file1);
|
||||
|
||||
let result = scene.cmd("id").arg("-gn").run();
|
||||
if skipping_test_is_okay(&result, "id: cannot find name for group ID") {
|
||||
return;
|
||||
}
|
||||
let group_name = String::from(result.stdout_str().trim());
|
||||
assert!(!group_name.is_empty());
|
||||
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg(format!("{}:{}", user_name, group_name))
|
||||
.arg("--verbose")
|
||||
.arg(file1)
|
||||
.run();
|
||||
if skipping_test_is_okay(&result, "chown: invalid group:") {
|
||||
return;
|
||||
}
|
||||
result.stderr_contains(&"retained as");
|
||||
|
||||
// check that username.groupname is understood
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg(format!("{}.{}", user_name, group_name))
|
||||
.arg("--verbose")
|
||||
.arg(file1)
|
||||
.run();
|
||||
if skipping_test_is_okay(&result, "chown: invalid group:") {
|
||||
return;
|
||||
}
|
||||
result.stderr_contains(&"retained as");
|
||||
|
||||
// Fails as user.name doesn't exist in the CI
|
||||
// but it is valid
|
||||
scene
|
||||
.ucmd()
|
||||
.arg(format!("{}:{}", "user.name", "groupname"))
|
||||
.arg("--verbose")
|
||||
.arg(file1)
|
||||
.fails()
|
||||
.stderr_contains(&"chown: invalid user: 'user.name:groupname'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
// FixME: on macos & freebsd group name is not recognized correctly: "chown: invalid group: ':groupname'
|
||||
#[cfg(any(
|
||||
|
@ -405,6 +498,19 @@ fn test_chown_owner_group_id() {
|
|||
}
|
||||
result.stderr_contains(&"retained as");
|
||||
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg(format!("{}.{}", user_id, group_id))
|
||||
.arg("--verbose")
|
||||
.arg(file1)
|
||||
.run();
|
||||
if skipping_test_is_okay(&result, "invalid user") {
|
||||
// From the Logs: "Build (ubuntu-18.04, x86_64-unknown-linux-gnu, feat_os_unix, use-cross)"
|
||||
// stderr: "chown: invalid user: '1001.116'
|
||||
return;
|
||||
}
|
||||
result.stderr_contains(&"retained as");
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("0:0")
|
||||
|
|
|
@ -23,7 +23,7 @@ fn test_enter_chroot_fails() {
|
|||
|
||||
assert!(result
|
||||
.stderr_str()
|
||||
.starts_with("chroot: cannot chroot to jail: Operation not permitted (os error 1)"));
|
||||
.starts_with("chroot: cannot chroot to 'jail': Operation not permitted (os error 1)"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -34,7 +34,7 @@ fn test_no_such_directory() {
|
|||
|
||||
ucmd.arg("a")
|
||||
.fails()
|
||||
.stderr_is("chroot: cannot change root directory to `a`: no such directory");
|
||||
.stderr_is("chroot: cannot change root directory to 'a': no such directory");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -68,7 +68,7 @@ fn test_invalid_file() {
|
|||
.arg(folder_name)
|
||||
.fails()
|
||||
.no_stdout()
|
||||
.stderr_contains("cksum: 'asdf' No such file or directory");
|
||||
.stderr_contains("cksum: asdf: No such file or directory");
|
||||
|
||||
// Then check when the file is of an invalid type
|
||||
at.mkdir(folder_name);
|
||||
|
@ -76,7 +76,7 @@ fn test_invalid_file() {
|
|||
.arg(folder_name)
|
||||
.fails()
|
||||
.no_stdout()
|
||||
.stderr_contains("cksum: 'asdf' Is a directory");
|
||||
.stderr_contains("cksum: asdf: Is a directory");
|
||||
}
|
||||
|
||||
// Make sure crc is correct for files larger than 32 bytes
|
||||
|
|
|
@ -434,10 +434,7 @@ fn test_ls_long_symlink_color() {
|
|||
let mut result_lines = result
|
||||
.stdout_str()
|
||||
.lines()
|
||||
.filter_map(|line| match line.starts_with("lrwx") {
|
||||
true => Some(line),
|
||||
false => None,
|
||||
})
|
||||
.filter(|line| line.starts_with("lrwx"))
|
||||
.enumerate();
|
||||
|
||||
// For each enumerated line, we assert that the output of ls matches the expected output.
|
||||
|
@ -457,14 +454,12 @@ fn test_ls_long_symlink_color() {
|
|||
|
||||
// We look up the Colors that are expected in `colors` using the ColorReferences
|
||||
// stored in `expected_output`.
|
||||
let expected_name_color = match expected_output[i].0 {
|
||||
Some(color_reference) => Some(colors[color_reference[0]][color_reference[1]].as_str()),
|
||||
None => None,
|
||||
};
|
||||
let expected_target_color = match expected_output[i].2 {
|
||||
Some(color_reference) => Some(colors[color_reference[0]][color_reference[1]].as_str()),
|
||||
None => None,
|
||||
};
|
||||
let expected_name_color = expected_output[i]
|
||||
.0
|
||||
.map(|color_reference| colors[color_reference[0]][color_reference[1]].as_str());
|
||||
let expected_target_color = expected_output[i]
|
||||
.2
|
||||
.map(|color_reference| colors[color_reference[0]][color_reference[1]].as_str());
|
||||
|
||||
// This is the important part. The asserts inside assert_names_and_colors_are_equal
|
||||
// will panic if the colors or names do not match the expected colors or names.
|
||||
|
@ -472,11 +467,11 @@ fn test_ls_long_symlink_color() {
|
|||
// don't expect any color here, as in `expected_output[2], or don't know what specific
|
||||
// color to expect yet, as in expected_output[0:1].
|
||||
assert_names_and_colors_are_equal(
|
||||
&matched_name_color,
|
||||
matched_name_color,
|
||||
expected_name_color,
|
||||
&matched_name,
|
||||
expected_output[i].1,
|
||||
&matched_target_color,
|
||||
matched_target_color,
|
||||
expected_target_color,
|
||||
&matched_target,
|
||||
expected_output[i].3,
|
||||
|
@ -507,6 +502,7 @@ fn test_ls_long_symlink_color() {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn assert_names_and_colors_are_equal(
|
||||
name_color: &str,
|
||||
expected_name_color: Option<&str>,
|
||||
|
@ -532,7 +528,7 @@ fn test_ls_long_symlink_color() {
|
|||
|
||||
fn capture_colored_string(input: &str) -> (Color, Name) {
|
||||
let colored_name = Regex::new(r"\x1b\[([0-9;]+)m(.+)\x1b\[0m").unwrap();
|
||||
match colored_name.captures(&input) {
|
||||
match colored_name.captures(input) {
|
||||
Some(captures) => (
|
||||
captures.get(1).unwrap().as_str().to_string(),
|
||||
captures.get(2).unwrap().as_str().to_string(),
|
||||
|
|
|
@ -531,7 +531,7 @@ fn test_keys_invalid_field() {
|
|||
new_ucmd!()
|
||||
.args(&["-k", "1."])
|
||||
.fails()
|
||||
.stderr_only("sort: failed to parse key `1.`: failed to parse character index ``: cannot parse integer from empty string");
|
||||
.stderr_only("sort: failed to parse key '1.': failed to parse character index '': cannot parse integer from empty string");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -539,7 +539,7 @@ fn test_keys_invalid_field_option() {
|
|||
new_ucmd!()
|
||||
.args(&["-k", "1.1x"])
|
||||
.fails()
|
||||
.stderr_only("sort: failed to parse key `1.1x`: invalid option: `x`");
|
||||
.stderr_only("sort: failed to parse key '1.1x': invalid option: 'x'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -547,7 +547,7 @@ fn test_keys_invalid_field_zero() {
|
|||
new_ucmd!()
|
||||
.args(&["-k", "0.1"])
|
||||
.fails()
|
||||
.stderr_only("sort: failed to parse key `0.1`: field index can not be 0");
|
||||
.stderr_only("sort: failed to parse key '0.1': field index can not be 0");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -555,7 +555,7 @@ fn test_keys_invalid_char_zero() {
|
|||
new_ucmd!()
|
||||
.args(&["-k", "1.0"])
|
||||
.fails()
|
||||
.stderr_only("sort: failed to parse key `1.0`: invalid character index 0 for the start position of a field");
|
||||
.stderr_only("sort: failed to parse key '1.0': invalid character index 0 for the start position of a field");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -59,7 +59,7 @@ fn test_invalid_file() {
|
|||
|
||||
at.mkdir("a");
|
||||
|
||||
ucmd.arg("a").fails().stderr_is("sum: 'a' Is a directory");
|
||||
ucmd.arg("a").fails().stderr_is("sum: a: Is a directory");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -68,5 +68,5 @@ fn test_invalid_metadata() {
|
|||
|
||||
ucmd.arg("b")
|
||||
.fails()
|
||||
.stderr_is("sum: 'b' No such file or directory");
|
||||
.stderr_is("sum: b: No such file or directory");
|
||||
}
|
||||
|
|
|
@ -320,7 +320,7 @@ fn test_invalid_utf8_integer_compare() {
|
|||
|
||||
cmd.run()
|
||||
.status_code(2)
|
||||
.stderr_is("test: invalid integer 'fo<66>o'");
|
||||
.stderr_is("test: invalid integer $'fo\\x80o'");
|
||||
|
||||
let mut cmd = new_ucmd!();
|
||||
cmd.raw.arg(arg);
|
||||
|
@ -328,7 +328,7 @@ fn test_invalid_utf8_integer_compare() {
|
|||
|
||||
cmd.run()
|
||||
.status_code(2)
|
||||
.stderr_is("test: invalid integer 'fo<66>o'");
|
||||
.stderr_is("test: invalid integer $'fo\\x80o'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -6,6 +6,7 @@ use self::touch::filetime::{self, FileTime};
|
|||
extern crate time;
|
||||
|
||||
use crate::common::util::*;
|
||||
use std::fs::remove_file;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn get_file_times(at: &AtPath, path: &str) -> (FileTime, FileTime) {
|
||||
|
@ -323,7 +324,8 @@ fn test_touch_no_dereference() {
|
|||
|
||||
#[test]
|
||||
fn test_touch_reference() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let scenario = TestScenario::new("touch");
|
||||
let (at, mut _ucmd) = (scenario.fixtures.clone(), scenario.ucmd());
|
||||
let file_a = "test_touch_reference_a";
|
||||
let file_b = "test_touch_reference_b";
|
||||
let start_of_year = str_to_filetime("%Y%m%d%H%M", "201501010000");
|
||||
|
@ -331,15 +333,21 @@ fn test_touch_reference() {
|
|||
at.touch(file_a);
|
||||
set_file_times(&at, file_a, start_of_year, start_of_year);
|
||||
assert!(at.file_exists(file_a));
|
||||
for &opt in &["-r", "--ref", "--reference"] {
|
||||
scenario
|
||||
.ccmd("touch")
|
||||
.args(&[opt, file_a, file_b])
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
ucmd.args(&["-r", file_a, file_b]).succeeds().no_stderr();
|
||||
assert!(at.file_exists(file_b));
|
||||
|
||||
assert!(at.file_exists(file_b));
|
||||
|
||||
let (atime, mtime) = get_file_times(&at, file_b);
|
||||
assert_eq!(atime, mtime);
|
||||
assert_eq!(atime, start_of_year);
|
||||
assert_eq!(mtime, start_of_year);
|
||||
let (atime, mtime) = get_file_times(&at, file_b);
|
||||
assert_eq!(atime, mtime);
|
||||
assert_eq!(atime, start_of_year);
|
||||
assert_eq!(mtime, start_of_year);
|
||||
let _ = remove_file(file_b);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -66,10 +66,23 @@ fn test_wrong_argument() {
|
|||
|
||||
#[test]
|
||||
// FixME: freebsd panic
|
||||
#[cfg(not(any(windows, target_os = "freebsd")))]
|
||||
#[cfg(all(unix, not(target_os = "freebsd")))]
|
||||
fn test_stdout_fail() {
|
||||
let mut child = new_ucmd!().run_no_wait();
|
||||
drop(child.stdout.take());
|
||||
let status = child.wait().unwrap();
|
||||
use std::process::{Command, Stdio};
|
||||
let ts = TestScenario::new(util_name!());
|
||||
// Sleep inside a shell to ensure the process doesn't finish before we've
|
||||
// closed its stdout
|
||||
let mut proc = Command::new("sh")
|
||||
.arg("-c")
|
||||
.arg(format!(
|
||||
"sleep 0.2; exec {} {}",
|
||||
ts.bin_path.to_str().unwrap(),
|
||||
ts.util_name
|
||||
))
|
||||
.stdout(Stdio::piped())
|
||||
.spawn()
|
||||
.unwrap();
|
||||
drop(proc.stdout.take());
|
||||
let status = proc.wait().unwrap();
|
||||
assert_eq!(status.code(), Some(3));
|
||||
}
|
||||
|
|
|
@ -23,23 +23,24 @@ fn test_unlink_multiple_files() {
|
|||
at.touch(file_a);
|
||||
at.touch(file_b);
|
||||
|
||||
ucmd.arg(file_a).arg(file_b).fails().stderr_is(&format!(
|
||||
"{0}: extra operand: 'test_unlink_multiple_file_b'\nTry '{1} {0} --help' for more information.",
|
||||
ts.util_name,
|
||||
ts.bin_path.to_string_lossy()
|
||||
));
|
||||
ucmd.arg(file_a)
|
||||
.arg(file_b)
|
||||
.fails()
|
||||
.stderr_contains("USAGE");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unlink_directory() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let dir = "test_unlink_empty_directory";
|
||||
let dir = "dir";
|
||||
|
||||
at.mkdir(dir);
|
||||
|
||||
ucmd.arg(dir).fails().stderr_is(
|
||||
"unlink: cannot unlink 'test_unlink_empty_directory': Not a regular file \
|
||||
or symlink\n",
|
||||
let res = ucmd.arg(dir).fails();
|
||||
let stderr = res.stderr_str();
|
||||
assert!(
|
||||
stderr == "unlink: cannot unlink 'dir': Is a directory\n"
|
||||
|| stderr == "unlink: cannot unlink 'dir': Permission denied\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -47,8 +48,21 @@ fn test_unlink_directory() {
|
|||
fn test_unlink_nonexistent() {
|
||||
let file = "test_unlink_nonexistent";
|
||||
|
||||
new_ucmd!().arg(file).fails().stderr_is(
|
||||
"unlink: Cannot stat 'test_unlink_nonexistent': No such file or directory \
|
||||
(os error 2)\n",
|
||||
);
|
||||
new_ucmd!()
|
||||
.arg(file)
|
||||
.fails()
|
||||
.stderr_is("unlink: cannot unlink 'test_unlink_nonexistent': No such file or directory\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_unlink_symlink() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
|
||||
at.touch("foo");
|
||||
at.symlink_file("foo", "bar");
|
||||
|
||||
ucmd.arg("bar").succeeds().no_stderr();
|
||||
|
||||
assert!(at.file_exists("foo"));
|
||||
assert!(!at.file_exists("bar"));
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue