mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-08-01 21:47:46 +00:00
Merge branch 'master' into id_selinux_context
This commit is contained in:
commit
e53f4db33a
260 changed files with 7579 additions and 4977 deletions
|
@ -103,7 +103,7 @@ fn test_wrap_bad_arg() {
|
|||
.arg(wrap_param)
|
||||
.arg("b")
|
||||
.fails()
|
||||
.stderr_only("base32: Invalid wrap size: ‘b’: invalid digit found in string\n");
|
||||
.stderr_only("base32: Invalid wrap size: 'b': invalid digit found in string\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,7 @@ fn test_base32_extra_operand() {
|
|||
.arg("a.txt")
|
||||
.arg("a.txt")
|
||||
.fails()
|
||||
.stderr_only("base32: extra operand ‘a.txt’");
|
||||
.stderr_only("base32: extra operand 'a.txt'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -89,7 +89,7 @@ fn test_wrap_bad_arg() {
|
|||
.arg(wrap_param)
|
||||
.arg("b")
|
||||
.fails()
|
||||
.stderr_only("base64: Invalid wrap size: ‘b’: invalid digit found in string\n");
|
||||
.stderr_only("base64: Invalid wrap size: 'b': invalid digit found in string\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ fn test_base64_extra_operand() {
|
|||
.arg("a.txt")
|
||||
.arg("a.txt")
|
||||
.fails()
|
||||
.stderr_only("base64: extra operand ‘a.txt’");
|
||||
.stderr_only("base64: extra operand 'a.txt'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -172,14 +172,14 @@ fn test_chown_only_colon() {
|
|||
// expected:
|
||||
// $ chown -v :: file.txt 2>out_err ; echo $? ; cat out_err
|
||||
// 1
|
||||
// chown: invalid group: ‘::’
|
||||
// chown: invalid group: '::'
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("::")
|
||||
.arg("--verbose")
|
||||
.arg(file1)
|
||||
.fails()
|
||||
.stderr_contains(&"invalid group: ‘::’");
|
||||
.stderr_contains(&"invalid group: '::'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1325,3 +1325,16 @@ fn test_copy_dir_with_symlinks() {
|
|||
ucmd.args(&["-r", "dir", "copy"]).succeeds();
|
||||
assert_eq!(at.resolve_link("copy/file-link"), "file");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(windows))]
|
||||
fn test_copy_symlink_force() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
at.touch("file");
|
||||
at.symlink_file("file", "file-link");
|
||||
at.touch("copy");
|
||||
|
||||
ucmd.args(&["file-link", "copy", "-f", "--no-dereference"])
|
||||
.succeeds();
|
||||
assert_eq!(at.resolve_link("copy"), "file");
|
||||
}
|
||||
|
|
|
@ -162,7 +162,7 @@ fn test_directory_and_no_such_file() {
|
|||
fn test_equal_as_delimiter() {
|
||||
new_ucmd!()
|
||||
.args(&["-f", "2", "-d="])
|
||||
.pipe_in("--libdir=./out/lib")
|
||||
.pipe_in("--dir=./out/lib")
|
||||
.succeeds()
|
||||
.stdout_only("./out/lib\n");
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ fn test_date_format_without_plus() {
|
|||
new_ucmd!()
|
||||
.arg("%s")
|
||||
.fails()
|
||||
.stderr_contains("date: invalid date ‘%s’")
|
||||
.stderr_contains("date: invalid date '%s'")
|
||||
.code_is(1);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
use crate::common::util::*;
|
||||
|
||||
const SUB_DIR: &str = "subdir/deeper";
|
||||
const SUB_DEEPER_DIR: &str = "subdir/deeper/deeper_dir";
|
||||
const SUB_DIR_LINKS: &str = "subdir/links";
|
||||
const SUB_DIR_LINKS_DEEPER_SYM_DIR: &str = "subdir/links/deeper_dir";
|
||||
const SUB_FILE: &str = "subdir/links/subwords.txt";
|
||||
const SUB_LINK: &str = "subdir/links/sublink.txt";
|
||||
|
||||
|
@ -21,7 +23,7 @@ fn _du_basics(s: &str) {
|
|||
let answer = "32\t./subdir
|
||||
8\t./subdir/deeper
|
||||
24\t./subdir/links
|
||||
40\t./
|
||||
40\t.
|
||||
";
|
||||
assert_eq!(s, answer);
|
||||
}
|
||||
|
@ -30,7 +32,7 @@ fn _du_basics(s: &str) {
|
|||
let answer = "28\t./subdir
|
||||
8\t./subdir/deeper
|
||||
16\t./subdir/links
|
||||
36\t./
|
||||
36\t.
|
||||
";
|
||||
assert_eq!(s, answer);
|
||||
}
|
||||
|
@ -54,15 +56,15 @@ fn test_du_basics_subdir() {
|
|||
|
||||
#[cfg(target_vendor = "apple")]
|
||||
fn _du_basics_subdir(s: &str) {
|
||||
assert_eq!(s, "4\tsubdir/deeper\n");
|
||||
assert_eq!(s, "4\tsubdir/deeper/deeper_dir\n8\tsubdir/deeper\n");
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
fn _du_basics_subdir(s: &str) {
|
||||
assert_eq!(s, "0\tsubdir/deeper\n");
|
||||
assert_eq!(s, "0\tsubdir/deeper\\deeper_dir\n0\tsubdir/deeper\n");
|
||||
}
|
||||
#[cfg(target_os = "freebsd")]
|
||||
fn _du_basics_subdir(s: &str) {
|
||||
assert_eq!(s, "8\tsubdir/deeper\n");
|
||||
assert_eq!(s, "8\tsubdir/deeper/deeper_dir\n16\tsubdir/deeper\n");
|
||||
}
|
||||
#[cfg(all(
|
||||
not(target_vendor = "apple"),
|
||||
|
@ -210,12 +212,7 @@ fn test_du_d_flag() {
|
|||
{
|
||||
let result_reference = scene.cmd("du").arg("-d1").run();
|
||||
if result_reference.succeeded() {
|
||||
assert_eq!(
|
||||
// TODO: gnu `du` doesn't use trailing "/" here
|
||||
// result.stdout_str(), result_reference.stdout_str()
|
||||
result.stdout_str().trim_end_matches("/\n"),
|
||||
result_reference.stdout_str().trim_end_matches('\n')
|
||||
);
|
||||
assert_eq!(result.stdout_str(), result_reference.stdout_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -224,15 +221,15 @@ fn test_du_d_flag() {
|
|||
|
||||
#[cfg(target_vendor = "apple")]
|
||||
fn _du_d_flag(s: &str) {
|
||||
assert_eq!(s, "16\t./subdir\n20\t./\n");
|
||||
assert_eq!(s, "20\t./subdir\n24\t.\n");
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
fn _du_d_flag(s: &str) {
|
||||
assert_eq!(s, "8\t./subdir\n8\t./\n");
|
||||
assert_eq!(s, "8\t.\\subdir\n8\t.\n");
|
||||
}
|
||||
#[cfg(target_os = "freebsd")]
|
||||
fn _du_d_flag(s: &str) {
|
||||
assert_eq!(s, "28\t./subdir\n36\t./\n");
|
||||
assert_eq!(s, "36\t./subdir\n44\t.\n");
|
||||
}
|
||||
#[cfg(all(
|
||||
not(target_vendor = "apple"),
|
||||
|
@ -242,9 +239,127 @@ fn _du_d_flag(s: &str) {
|
|||
fn _du_d_flag(s: &str) {
|
||||
// MS-WSL linux has altered expected output
|
||||
if !uucore::os::is_wsl_1() {
|
||||
assert_eq!(s, "28\t./subdir\n36\t./\n");
|
||||
assert_eq!(s, "28\t./subdir\n36\t.\n");
|
||||
} else {
|
||||
assert_eq!(s, "8\t./subdir\n8\t./\n");
|
||||
assert_eq!(s, "8\t./subdir\n8\t.\n");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_du_dereference() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
at.symlink_dir(SUB_DEEPER_DIR, SUB_DIR_LINKS_DEEPER_SYM_DIR);
|
||||
|
||||
let result = scene.ucmd().arg("-L").arg(SUB_DIR_LINKS).succeeds();
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let result_reference = scene.cmd("du").arg("-L").arg(SUB_DIR_LINKS).run();
|
||||
if result_reference.succeeded() {
|
||||
assert_eq!(result.stdout_str(), result_reference.stdout_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_du_dereference(result.stdout_str());
|
||||
}
|
||||
|
||||
#[cfg(target_vendor = "apple")]
|
||||
fn _du_dereference(s: &str) {
|
||||
assert_eq!(s, "4\tsubdir/links/deeper_dir\n16\tsubdir/links\n");
|
||||
}
|
||||
#[cfg(target_os = "windows")]
|
||||
fn _du_dereference(s: &str) {
|
||||
assert_eq!(s, "0\tsubdir/links\\deeper_dir\n8\tsubdir/links\n");
|
||||
}
|
||||
#[cfg(target_os = "freebsd")]
|
||||
fn _du_dereference(s: &str) {
|
||||
assert_eq!(s, "8\tsubdir/links/deeper_dir\n24\tsubdir/links\n");
|
||||
}
|
||||
#[cfg(all(
|
||||
not(target_vendor = "apple"),
|
||||
not(target_os = "windows"),
|
||||
not(target_os = "freebsd")
|
||||
))]
|
||||
fn _du_dereference(s: &str) {
|
||||
// MS-WSL linux has altered expected output
|
||||
if !uucore::os::is_wsl_1() {
|
||||
assert_eq!(s, "8\tsubdir/links/deeper_dir\n24\tsubdir/links\n");
|
||||
} else {
|
||||
assert_eq!(s, "0\tsubdir/links/deeper_dir\n8\tsubdir/links\n");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_du_inodes_basic() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let result = scene.ucmd().arg("--inodes").succeeds();
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let result_reference = scene.cmd("du").arg("--inodes").run();
|
||||
assert_eq!(result.stdout_str(), result_reference.stdout_str());
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
_du_inodes_basic(result.stdout_str());
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn _du_inodes_basic(s: &str) {
|
||||
assert_eq!(
|
||||
s,
|
||||
"2\t.\\subdir\\deeper\\deeper_dir
|
||||
4\t.\\subdir\\deeper
|
||||
3\t.\\subdir\\links
|
||||
8\t.\\subdir
|
||||
11\t.
|
||||
"
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
fn _du_inodes_basic(s: &str) {
|
||||
assert_eq!(
|
||||
s,
|
||||
"2\t./subdir/deeper/deeper_dir
|
||||
4\t./subdir/deeper
|
||||
3\t./subdir/links
|
||||
8\t./subdir
|
||||
11\t.
|
||||
"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_du_inodes() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--summarize")
|
||||
.arg("--inodes")
|
||||
.succeeds()
|
||||
.stdout_only("11\t.\n");
|
||||
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg("--separate-dirs")
|
||||
.arg("--inodes")
|
||||
.succeeds();
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
result.stdout_contains("3\t.\\subdir\\links\n");
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
result.stdout_contains("3\t./subdir/links\n");
|
||||
result.stdout_contains("3\t.\n");
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let result_reference = scene.cmd("du").arg("--separate-dirs").arg("--inodes").run();
|
||||
assert_eq!(result.stdout_str(), result_reference.stdout_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,7 +426,7 @@ fn test_du_no_permission() {
|
|||
|
||||
let result = scene.ucmd().arg(SUB_DIR_LINKS).run(); // TODO: replace with ".fails()" once `du` is fixed
|
||||
result.stderr_contains(
|
||||
"du: cannot read directory ‘subdir/links‘: Permission denied (os error 13)",
|
||||
"du: cannot read directory 'subdir/links': Permission denied (os error 13)",
|
||||
);
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
|
@ -366,12 +481,105 @@ fn test_du_threshold() {
|
|||
.arg(format!("--threshold={}", threshold))
|
||||
.succeeds()
|
||||
.stdout_contains("links")
|
||||
.stdout_does_not_contain("deeper");
|
||||
.stdout_does_not_contain("deeper_dir");
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg(format!("--threshold=-{}", threshold))
|
||||
.succeeds()
|
||||
.stdout_does_not_contain("links")
|
||||
.stdout_contains("deeper");
|
||||
.stdout_contains("deeper_dir");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_du_apparent_size() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let result = scene.ucmd().arg("--apparent-size").succeeds();
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let result_reference = scene.cmd("du").arg("--apparent-size").run();
|
||||
assert_eq!(result.stdout_str(), result_reference.stdout_str());
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
_du_apparent_size(result.stdout_str());
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
fn _du_apparent_size(s: &str) {
|
||||
assert_eq!(
|
||||
s,
|
||||
"1\t.\\subdir\\deeper\\deeper_dir
|
||||
1\t.\\subdir\\deeper
|
||||
6\t.\\subdir\\links
|
||||
6\t.\\subdir
|
||||
6\t.
|
||||
"
|
||||
);
|
||||
}
|
||||
#[cfg(target_vendor = "apple")]
|
||||
fn _du_apparent_size(s: &str) {
|
||||
assert_eq!(
|
||||
s,
|
||||
"1\t./subdir/deeper/deeper_dir
|
||||
1\t./subdir/deeper
|
||||
6\t./subdir/links
|
||||
6\t./subdir
|
||||
6\t.
|
||||
"
|
||||
);
|
||||
}
|
||||
#[cfg(target_os = "freebsd")]
|
||||
fn _du_apparent_size(s: &str) {
|
||||
assert_eq!(
|
||||
s,
|
||||
"1\t./subdir/deeper/deeper_dir
|
||||
2\t./subdir/deeper
|
||||
6\t./subdir/links
|
||||
8\t./subdir
|
||||
8\t.
|
||||
"
|
||||
);
|
||||
}
|
||||
#[cfg(all(
|
||||
not(target_vendor = "apple"),
|
||||
not(target_os = "windows"),
|
||||
not(target_os = "freebsd")
|
||||
))]
|
||||
fn _du_apparent_size(s: &str) {
|
||||
assert_eq!(
|
||||
s,
|
||||
"5\t./subdir/deeper/deeper_dir
|
||||
9\t./subdir/deeper
|
||||
10\t./subdir/links
|
||||
22\t./subdir
|
||||
26\t.
|
||||
"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_du_bytes() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let result = scene.ucmd().arg("--bytes").succeeds();
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
let result_reference = scene.cmd("du").arg("--bytes").run();
|
||||
assert_eq!(result.stdout_str(), result_reference.stdout_str());
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
result.stdout_contains("5145\t.\\subdir\n");
|
||||
#[cfg(target_vendor = "apple")]
|
||||
result.stdout_contains("5625\t./subdir\n");
|
||||
#[cfg(target_os = "freebsd")]
|
||||
result.stdout_contains("7193\t./subdir\n");
|
||||
#[cfg(all(
|
||||
not(target_vendor = "apple"),
|
||||
not(target_os = "windows"),
|
||||
not(target_os = "freebsd")
|
||||
))]
|
||||
result.stdout_contains("21529\t./subdir\n");
|
||||
}
|
||||
|
|
|
@ -1,56 +1,176 @@
|
|||
use crate::common::util::*;
|
||||
|
||||
// spell-checker:ignore (ToDO) coreutil
|
||||
|
||||
// These tests run the GNU coreutils `(g)groups` binary in `$PATH` in order to gather reference values.
|
||||
// If the `(g)groups` in `$PATH` doesn't include a coreutils version string,
|
||||
// or the version is too low, the test is skipped.
|
||||
|
||||
// The reference version is 8.32. Here 8.30 was chosen because right now there's no
|
||||
// ubuntu image for github action available with a higher version than 8.30.
|
||||
const VERSION_MIN: &str = "8.30"; // minimum Version for the reference `groups` in $PATH
|
||||
const VERSION_MIN_MULTIPLE_USERS: &str = "8.31"; // this feature was introduced in GNU's coreutils 8.31
|
||||
const UUTILS_WARNING: &str = "uutils-tests-warning";
|
||||
const UUTILS_INFO: &str = "uutils-tests-info";
|
||||
|
||||
macro_rules! unwrap_or_return {
|
||||
( $e:expr ) => {
|
||||
match $e {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
println!("{}: test skipped: {}", UUTILS_INFO, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn whoami() -> String {
|
||||
// Apparently some CI environments have configuration issues, e.g. with 'whoami' and 'id'.
|
||||
//
|
||||
// From the Logs: "Build (ubuntu-18.04, x86_64-unknown-linux-gnu, feat_os_unix, use-cross)"
|
||||
// whoami: cannot find name for user ID 1001
|
||||
// id --name: cannot find name for user ID 1001
|
||||
// id --name: cannot find name for group ID 116
|
||||
//
|
||||
// However, when running "id" from within "/bin/bash" it looks fine:
|
||||
// id: "uid=1001(runner) gid=118(docker) groups=118(docker),4(adm),101(systemd-journal)"
|
||||
// whoami: "runner"
|
||||
|
||||
// Use environment variable to get current user instead of
|
||||
// invoking `whoami` and fall back to user "nobody" on error.
|
||||
std::env::var("USER").unwrap_or_else(|e| {
|
||||
println!("{}: {}, using \"nobody\" instead", UUTILS_WARNING, e);
|
||||
"nobody".to_string()
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_groups() {
|
||||
if !is_ci() {
|
||||
new_ucmd!().succeeds().stdout_is(expected_result(&[]));
|
||||
} else {
|
||||
// TODO: investigate how this could be tested in CI
|
||||
// stderr = groups: cannot find name for group ID 116
|
||||
println!("test skipped:");
|
||||
}
|
||||
let result = new_ucmd!().run();
|
||||
let exp_result = unwrap_or_return!(expected_result(&[]));
|
||||
|
||||
result
|
||||
.stdout_is(exp_result.stdout_str())
|
||||
.stderr_is(exp_result.stderr_str())
|
||||
.code_is(exp_result.code());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
#[ignore = "fixme: 'groups USERNAME' needs more debugging"]
|
||||
fn test_groups_username() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let whoami_result = scene.cmd("whoami").run();
|
||||
let test_users = [&whoami()[..]];
|
||||
|
||||
let username = if whoami_result.succeeded() {
|
||||
whoami_result.stdout_move_str()
|
||||
} else if is_ci() {
|
||||
String::from("docker")
|
||||
} else {
|
||||
println!("test skipped:");
|
||||
let result = new_ucmd!().args(&test_users).run();
|
||||
let exp_result = unwrap_or_return!(expected_result(&test_users));
|
||||
|
||||
result
|
||||
.stdout_is(exp_result.stdout_str())
|
||||
.stderr_is(exp_result.stderr_str())
|
||||
.code_is(exp_result.code());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn test_groups_username_multiple() {
|
||||
// TODO: [2021-06; jhscheer] refactor this as `let util_name = host_name_for(util_name!())` when that function is added to 'tests/common'
|
||||
#[cfg(target_os = "linux")]
|
||||
let util_name = util_name!();
|
||||
#[cfg(all(unix, not(target_os = "linux")))]
|
||||
let util_name = &format!("g{}", util_name!());
|
||||
let version_check_string = check_coreutil_version(util_name, VERSION_MIN_MULTIPLE_USERS);
|
||||
if version_check_string.starts_with(UUTILS_WARNING) {
|
||||
println!("{}\ntest skipped", version_check_string);
|
||||
return;
|
||||
}
|
||||
let test_users = ["root", "man", "postfix", "sshd", &whoami()];
|
||||
|
||||
let result = new_ucmd!().args(&test_users).run();
|
||||
let exp_result = unwrap_or_return!(expected_result(&test_users));
|
||||
|
||||
result
|
||||
.stdout_is(exp_result.stdout_str())
|
||||
.stderr_is(exp_result.stderr_str())
|
||||
.code_is(exp_result.code());
|
||||
}
|
||||
|
||||
fn check_coreutil_version(util_name: &str, version_expected: &str) -> String {
|
||||
// example:
|
||||
// $ id --version | head -n 1
|
||||
// id (GNU coreutils) 8.32.162-4eda
|
||||
let scene = TestScenario::new(util_name);
|
||||
let version_check = scene
|
||||
.cmd_keepenv(&util_name)
|
||||
.env("LC_ALL", "C")
|
||||
.arg("--version")
|
||||
.run();
|
||||
version_check
|
||||
.stdout_str()
|
||||
.split('\n')
|
||||
.collect::<Vec<_>>()
|
||||
.get(0)
|
||||
.map_or_else(
|
||||
|| format!("{}: unexpected output format for reference coreutil: '{} --version'", UUTILS_WARNING, util_name),
|
||||
|s| {
|
||||
if s.contains(&format!("(GNU coreutils) {}", version_expected)) {
|
||||
s.to_string()
|
||||
} else if s.contains("(GNU coreutils)") {
|
||||
let version_found = s.split_whitespace().last().unwrap()[..4].parse::<f32>().unwrap_or_default();
|
||||
let version_expected = version_expected.parse::<f32>().unwrap_or_default();
|
||||
if version_found > version_expected {
|
||||
format!("{}: version for the reference coreutil '{}' is higher than expected; expected: {}, found: {}", UUTILS_INFO, util_name, version_expected, version_found)
|
||||
} else {
|
||||
format!("{}: version for the reference coreutil '{}' does not match; expected: {}, found: {}", UUTILS_WARNING, util_name, version_expected, version_found) }
|
||||
} else {
|
||||
format!("{}: no coreutils version string found for reference coreutils '{} --version'", UUTILS_WARNING, util_name)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[allow(clippy::needless_borrow)]
|
||||
#[cfg(unix)]
|
||||
fn expected_result(args: &[&str]) -> Result<CmdResult, String> {
|
||||
// TODO: [2021-06; jhscheer] refactor this as `let util_name = host_name_for(util_name!())` when that function is added to 'tests/common'
|
||||
#[cfg(target_os = "linux")]
|
||||
let util_name = util_name!();
|
||||
#[cfg(all(unix, not(target_os = "linux")))]
|
||||
let util_name = &format!("g{}", util_name!());
|
||||
|
||||
let version_check_string = check_coreutil_version(util_name, VERSION_MIN);
|
||||
if version_check_string.starts_with(UUTILS_WARNING) {
|
||||
return Err(version_check_string);
|
||||
}
|
||||
println!("{}", version_check_string);
|
||||
|
||||
let scene = TestScenario::new(util_name);
|
||||
let result = scene
|
||||
.cmd_keepenv(util_name)
|
||||
.env("LC_ALL", "C")
|
||||
.args(args)
|
||||
.run();
|
||||
|
||||
let (stdout, stderr): (String, String) = if cfg!(target_os = "linux") {
|
||||
(
|
||||
result.stdout_str().to_string(),
|
||||
result.stderr_str().to_string(),
|
||||
)
|
||||
} else {
|
||||
// strip 'g' prefix from results:
|
||||
let from = util_name.to_string() + ":";
|
||||
let to = &from[1..];
|
||||
(
|
||||
result.stdout_str().replace(&from, to),
|
||||
result.stderr_str().replace(&from, to),
|
||||
)
|
||||
};
|
||||
|
||||
// TODO: stdout should be in the form: "username : group1 group2 group3"
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg(&username)
|
||||
.succeeds()
|
||||
.stdout_is(expected_result(&[&username]));
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn expected_result(args: &[&str]) -> String {
|
||||
// We want to use GNU id. On most linux systems, this is "id", but on
|
||||
// bsd-like systems (e.g. FreeBSD, MacOS), it is commonly "gid".
|
||||
#[cfg(any(target_os = "linux"))]
|
||||
let util_name = "id";
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
let util_name = "gid";
|
||||
|
||||
TestScenario::new(util_name)
|
||||
.cmd_keepenv(util_name)
|
||||
.env("LANGUAGE", "C")
|
||||
.args(args)
|
||||
.args(&["-Gn"])
|
||||
.succeeds()
|
||||
.stdout_move_str()
|
||||
Ok(CmdResult::new(
|
||||
Some(result.tmpd()),
|
||||
Some(result.code()),
|
||||
result.succeeded(),
|
||||
stdout.as_bytes(),
|
||||
stderr.as_bytes(),
|
||||
))
|
||||
}
|
||||
|
|
|
@ -250,26 +250,48 @@ hello
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bad_utf8() {
|
||||
let bytes: &[u8] = b"\xfc\x80\x80\x80\x80\xaf";
|
||||
new_ucmd!()
|
||||
.args(&["-c", "6"])
|
||||
.pipe_in(bytes)
|
||||
.succeeds()
|
||||
.stdout_is_bytes(bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bad_utf8_lines() {
|
||||
let input: &[u8] =
|
||||
b"\xfc\x80\x80\x80\x80\xaf\nb\xfc\x80\x80\x80\x80\xaf\nb\xfc\x80\x80\x80\x80\xaf";
|
||||
let output = b"\xfc\x80\x80\x80\x80\xaf\nb\xfc\x80\x80\x80\x80\xaf\n";
|
||||
new_ucmd!()
|
||||
.args(&["-n", "2"])
|
||||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_is_bytes(output);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_head_invalid_num() {
|
||||
new_ucmd!()
|
||||
.args(&["-c", "1024R", "emptyfile.txt"])
|
||||
.fails()
|
||||
.stderr_is("head: invalid number of bytes: ‘1024R’");
|
||||
.stderr_is("head: invalid number of bytes: '1024R'");
|
||||
new_ucmd!()
|
||||
.args(&["-n", "1024R", "emptyfile.txt"])
|
||||
.fails()
|
||||
.stderr_is("head: invalid number of lines: ‘1024R’");
|
||||
.stderr_is("head: invalid number of lines: '1024R'");
|
||||
#[cfg(not(target_pointer_width = "128"))]
|
||||
new_ucmd!()
|
||||
.args(&["-c", "1Y", "emptyfile.txt"])
|
||||
.fails()
|
||||
.stderr_is("head: invalid number of bytes: ‘1Y’: Value too large for defined data type");
|
||||
.stderr_is("head: invalid number of bytes: '1Y': Value too large for defined data type");
|
||||
#[cfg(not(target_pointer_width = "128"))]
|
||||
new_ucmd!()
|
||||
.args(&["-n", "1Y", "emptyfile.txt"])
|
||||
.fails()
|
||||
.stderr_is("head: invalid number of lines: ‘1Y’: Value too large for defined data type");
|
||||
.stderr_is("head: invalid number of lines: '1Y': Value too large for defined data type");
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
{
|
||||
let sizes = ["1000G", "10T"];
|
||||
|
@ -279,7 +301,7 @@ fn test_head_invalid_num() {
|
|||
.fails()
|
||||
.code_is(1)
|
||||
.stderr_only(format!(
|
||||
"head: invalid number of bytes: ‘{}’: Value too large for defined data type",
|
||||
"head: invalid number of bytes: '{}': Value too large for defined data type",
|
||||
size
|
||||
));
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::common::util::*;
|
||||
|
||||
// spell-checker:ignore (ToDO) testsuite coreutil
|
||||
// spell-checker:ignore (ToDO) coreutil
|
||||
|
||||
// These tests run the GNU coreutils `(g)id` binary in `$PATH` in order to gather reference values.
|
||||
// If the `(g)id` in `$PATH` doesn't include a coreutils version string,
|
||||
|
@ -8,11 +8,12 @@ use crate::common::util::*;
|
|||
|
||||
// The reference version is 8.32. Here 8.30 was chosen because right now there's no
|
||||
// ubuntu image for github action available with a higher version than 8.30.
|
||||
const VERSION_EXPECTED: &str = "8.30"; // Version expected for the reference `id` in $PATH
|
||||
const VERSION_MULTIPLE_USERS: &str = "8.31";
|
||||
const VERSION_MIN: &str = "8.30"; // minimum Version for the reference `id` in $PATH
|
||||
const VERSION_MIN_MULTIPLE_USERS: &str = "8.31"; // this feature was introduced in GNU's coreutils 8.31
|
||||
const UUTILS_WARNING: &str = "uutils-tests-warning";
|
||||
const UUTILS_INFO: &str = "uutils-tests-info";
|
||||
|
||||
#[allow(clippy::needless_return)]
|
||||
macro_rules! unwrap_or_return {
|
||||
( $e:expr ) => {
|
||||
match $e {
|
||||
|
@ -202,13 +203,13 @@ fn test_id_multiple_users() {
|
|||
let util_name = util_name!();
|
||||
#[cfg(all(unix, not(target_os = "linux")))]
|
||||
let util_name = &format!("g{}", util_name!());
|
||||
let version_check_string = check_coreutil_version(util_name, VERSION_MULTIPLE_USERS);
|
||||
let version_check_string = check_coreutil_version(util_name, VERSION_MIN_MULTIPLE_USERS);
|
||||
if version_check_string.starts_with(UUTILS_WARNING) {
|
||||
println!("{}\ntest skipped", version_check_string);
|
||||
return;
|
||||
}
|
||||
|
||||
// Same typical users that GNU testsuite is using.
|
||||
// Same typical users that GNU test suite is using.
|
||||
let test_users = ["root", "man", "postfix", "sshd", &whoami()];
|
||||
|
||||
let scene = TestScenario::new(util_name!());
|
||||
|
@ -270,7 +271,7 @@ fn test_id_multiple_users_non_existing() {
|
|||
let util_name = util_name!();
|
||||
#[cfg(all(unix, not(target_os = "linux")))]
|
||||
let util_name = &format!("g{}", util_name!());
|
||||
let version_check_string = check_coreutil_version(util_name, VERSION_MULTIPLE_USERS);
|
||||
let version_check_string = check_coreutil_version(util_name, VERSION_MIN_MULTIPLE_USERS);
|
||||
if version_check_string.starts_with(UUTILS_WARNING) {
|
||||
println!("{}\ntest skipped", version_check_string);
|
||||
return;
|
||||
|
@ -502,7 +503,6 @@ fn test_id_no_specified_user_posixly() {
|
|||
"{}: test skipped: Kernel has no support for SElinux context",
|
||||
UUTILS_INFO
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
let result = scene.ucmd().succeeds();
|
||||
assert!(result.stdout_str().contains("context="));
|
||||
|
@ -517,7 +517,7 @@ fn check_coreutil_version(util_name: &str, version_expected: &str) -> String {
|
|||
let scene = TestScenario::new(util_name);
|
||||
let version_check = scene
|
||||
.cmd_keepenv(&util_name)
|
||||
.env("LANGUAGE", "C")
|
||||
.env("LC_ALL", "C")
|
||||
.arg("--version")
|
||||
.run();
|
||||
version_check
|
||||
|
@ -552,7 +552,7 @@ fn expected_result(args: &[&str]) -> Result<CmdResult, String> {
|
|||
#[cfg(all(unix, not(target_os = "linux")))]
|
||||
let util_name = &format!("g{}", util_name!());
|
||||
|
||||
let version_check_string = check_coreutil_version(util_name, VERSION_EXPECTED);
|
||||
let version_check_string = check_coreutil_version(util_name, VERSION_MIN);
|
||||
if version_check_string.starts_with(UUTILS_WARNING) {
|
||||
return Err(version_check_string);
|
||||
}
|
||||
|
@ -561,7 +561,7 @@ fn expected_result(args: &[&str]) -> Result<CmdResult, String> {
|
|||
let scene = TestScenario::new(util_name);
|
||||
let result = scene
|
||||
.cmd_keepenv(util_name)
|
||||
.env("LANGUAGE", "C")
|
||||
.env("LC_ALL", "C")
|
||||
.args(args)
|
||||
.run();
|
||||
|
||||
|
|
|
@ -674,3 +674,410 @@ fn test_install_creating_leading_dir_fails_on_long_name() {
|
|||
.fails()
|
||||
.stderr_contains("failed to create");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_dir() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let dir = "target_dir";
|
||||
let file1 = "source_file1";
|
||||
let file2 = "source_file2";
|
||||
|
||||
at.touch(file1);
|
||||
at.touch(file2);
|
||||
at.mkdir(dir);
|
||||
ucmd.arg(file1)
|
||||
.arg(file2)
|
||||
.arg(&format!("--target-directory={}", dir))
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file1));
|
||||
assert!(at.file_exists(file2));
|
||||
assert!(at.file_exists(&format!("{}/{}", dir, file1)));
|
||||
assert!(at.file_exists(&format!("{}/{}", dir, file2)));
|
||||
}
|
||||
//
|
||||
// test backup functionality
|
||||
#[test]
|
||||
fn test_install_backup_short_no_args_files() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file_a = "test_install_simple_backup_file_a";
|
||||
let file_b = "test_install_simple_backup_file_b";
|
||||
|
||||
at.touch(file_a);
|
||||
at.touch(file_b);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-b")
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file_a));
|
||||
assert!(at.file_exists(file_b));
|
||||
assert!(at.file_exists(&format!("{}~", file_b)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_backup_short_no_args_file_to_dir() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file = "test_install_simple_backup_file_a";
|
||||
let dest_dir = "test_install_dest/";
|
||||
let expect = format!("{}{}", dest_dir, file);
|
||||
|
||||
at.touch(file);
|
||||
at.mkdir(dest_dir);
|
||||
at.touch(&expect);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-b")
|
||||
.arg(file)
|
||||
.arg(dest_dir)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file));
|
||||
assert!(at.file_exists(&expect));
|
||||
assert!(at.file_exists(&format!("{}~", expect)));
|
||||
}
|
||||
|
||||
// Long --backup option is tested separately as it requires a slightly different
|
||||
// handling than '-b' does.
|
||||
#[test]
|
||||
fn test_install_backup_long_no_args_files() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file_a = "test_install_simple_backup_file_a";
|
||||
let file_b = "test_install_simple_backup_file_b";
|
||||
|
||||
at.touch(file_a);
|
||||
at.touch(file_b);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--backup")
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file_a));
|
||||
assert!(at.file_exists(file_b));
|
||||
assert!(at.file_exists(&format!("{}~", file_b)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_backup_long_no_args_file_to_dir() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file = "test_install_simple_backup_file_a";
|
||||
let dest_dir = "test_install_dest/";
|
||||
let expect = format!("{}{}", dest_dir, file);
|
||||
|
||||
at.touch(file);
|
||||
at.mkdir(dest_dir);
|
||||
at.touch(&expect);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--backup")
|
||||
.arg(file)
|
||||
.arg(dest_dir)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file));
|
||||
assert!(at.file_exists(&expect));
|
||||
assert!(at.file_exists(&format!("{}~", expect)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_backup_short_custom_suffix() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file_a = "test_install_backup_custom_suffix_file_a";
|
||||
let file_b = "test_install_backup_custom_suffix_file_b";
|
||||
let suffix = "super-suffix-of-the-century";
|
||||
|
||||
at.touch(file_a);
|
||||
at.touch(file_b);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-b")
|
||||
.arg(format!("--suffix={}", suffix))
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file_a));
|
||||
assert!(at.file_exists(file_b));
|
||||
assert!(at.file_exists(&format!("{}{}", file_b, suffix)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_backup_custom_suffix_via_env() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file_a = "test_install_backup_custom_suffix_file_a";
|
||||
let file_b = "test_install_backup_custom_suffix_file_b";
|
||||
let suffix = "super-suffix-of-the-century";
|
||||
|
||||
at.touch(file_a);
|
||||
at.touch(file_b);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-b")
|
||||
.env("SIMPLE_BACKUP_SUFFIX", suffix)
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file_a));
|
||||
assert!(at.file_exists(file_b));
|
||||
assert!(at.file_exists(&format!("{}{}", file_b, suffix)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_backup_numbered_with_t() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file_a = "test_install_backup_numbering_file_a";
|
||||
let file_b = "test_install_backup_numbering_file_b";
|
||||
|
||||
at.touch(file_a);
|
||||
at.touch(file_b);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--backup=t")
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file_a));
|
||||
assert!(at.file_exists(file_b));
|
||||
assert!(at.file_exists(&format!("{}.~1~", file_b)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_backup_numbered_with_numbered() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file_a = "test_install_backup_numbering_file_a";
|
||||
let file_b = "test_install_backup_numbering_file_b";
|
||||
|
||||
at.touch(file_a);
|
||||
at.touch(file_b);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--backup=numbered")
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file_a));
|
||||
assert!(at.file_exists(file_b));
|
||||
assert!(at.file_exists(&format!("{}.~1~", file_b)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_backup_existing() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file_a = "test_install_backup_numbering_file_a";
|
||||
let file_b = "test_install_backup_numbering_file_b";
|
||||
|
||||
at.touch(file_a);
|
||||
at.touch(file_b);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--backup=existing")
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file_a));
|
||||
assert!(at.file_exists(file_b));
|
||||
assert!(at.file_exists(&format!("{}~", file_b)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_backup_nil() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file_a = "test_install_backup_numbering_file_a";
|
||||
let file_b = "test_install_backup_numbering_file_b";
|
||||
|
||||
at.touch(file_a);
|
||||
at.touch(file_b);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--backup=nil")
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file_a));
|
||||
assert!(at.file_exists(file_b));
|
||||
assert!(at.file_exists(&format!("{}~", file_b)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_backup_numbered_if_existing_backup_existing() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file_a = "test_install_backup_numbering_file_a";
|
||||
let file_b = "test_install_backup_numbering_file_b";
|
||||
let file_b_backup = "test_install_backup_numbering_file_b.~1~";
|
||||
|
||||
at.touch(file_a);
|
||||
at.touch(file_b);
|
||||
at.touch(file_b_backup);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--backup=existing")
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file_a));
|
||||
assert!(at.file_exists(file_b));
|
||||
assert!(at.file_exists(file_b_backup));
|
||||
assert!(at.file_exists(&*format!("{}.~2~", file_b)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_backup_numbered_if_existing_backup_nil() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file_a = "test_install_backup_numbering_file_a";
|
||||
let file_b = "test_install_backup_numbering_file_b";
|
||||
let file_b_backup = "test_install_backup_numbering_file_b.~1~";
|
||||
|
||||
at.touch(file_a);
|
||||
at.touch(file_b);
|
||||
at.touch(file_b_backup);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--backup=nil")
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file_a));
|
||||
assert!(at.file_exists(file_b));
|
||||
assert!(at.file_exists(file_b_backup));
|
||||
assert!(at.file_exists(&*format!("{}.~2~", file_b)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_backup_simple() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file_a = "test_install_backup_numbering_file_a";
|
||||
let file_b = "test_install_backup_numbering_file_b";
|
||||
|
||||
at.touch(file_a);
|
||||
at.touch(file_b);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--backup=simple")
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file_a));
|
||||
assert!(at.file_exists(file_b));
|
||||
assert!(at.file_exists(&format!("{}~", file_b)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_backup_never() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file_a = "test_install_backup_numbering_file_a";
|
||||
let file_b = "test_install_backup_numbering_file_b";
|
||||
|
||||
at.touch(file_a);
|
||||
at.touch(file_b);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--backup=never")
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file_a));
|
||||
assert!(at.file_exists(file_b));
|
||||
assert!(at.file_exists(&format!("{}~", file_b)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_backup_none() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file_a = "test_install_backup_numbering_file_a";
|
||||
let file_b = "test_install_backup_numbering_file_b";
|
||||
|
||||
at.touch(file_a);
|
||||
at.touch(file_b);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--backup=none")
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file_a));
|
||||
assert!(at.file_exists(file_b));
|
||||
assert!(!at.file_exists(&format!("{}~", file_b)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_backup_off() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file_a = "test_install_backup_numbering_file_a";
|
||||
let file_b = "test_install_backup_numbering_file_b";
|
||||
|
||||
at.touch(file_a);
|
||||
at.touch(file_b);
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--backup=off")
|
||||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
|
||||
assert!(at.file_exists(file_a));
|
||||
assert!(at.file_exists(file_b));
|
||||
assert!(!at.file_exists(&format!("{}~", file_b)));
|
||||
}
|
||||
|
|
|
@ -580,3 +580,11 @@ fn test_relative_src_already_symlink() {
|
|||
ucmd.arg("-sr").arg("file2").arg("file3").succeeds();
|
||||
assert!(at.resolve_link("file3").ends_with("file1"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_relative_recursive() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
at.mkdir("dir");
|
||||
ucmd.args(&["-sr", "dir", "dir/recursive"]).succeeds();
|
||||
assert_eq!(at.resolve_link("dir/recursive"), ".");
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ fn test_ls_width() {
|
|||
.ucmd()
|
||||
.args(&option.split(' ').collect::<Vec<_>>())
|
||||
.fails()
|
||||
.stderr_only("ls: invalid line width: ‘1a’");
|
||||
.stderr_only("ls: invalid line width: '1a'");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2021,3 +2021,28 @@ fn test_ls_path() {
|
|||
.run()
|
||||
.stdout_is(expected_stdout);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ls_dangling_symlinks() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
at.mkdir("temp_dir");
|
||||
at.symlink_file("does_not_exist", "temp_dir/dangle");
|
||||
|
||||
scene.ucmd().arg("-L").arg("temp_dir/dangle").fails();
|
||||
scene.ucmd().arg("-H").arg("temp_dir/dangle").fails();
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("temp_dir/dangle")
|
||||
.succeeds()
|
||||
.stdout_contains("dangle");
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-Li")
|
||||
.arg("temp_dir")
|
||||
.succeeds() // this should fail, though at the moment, ls lacks a way to propagate errors encountered during display
|
||||
.stdout_contains(if cfg!(windows) { "dangle" } else { "? dangle" });
|
||||
}
|
||||
|
|
|
@ -17,7 +17,10 @@ static TEST_TEMPLATE8: &str = "tempXXXl/ate";
|
|||
#[cfg(windows)]
|
||||
static TEST_TEMPLATE8: &str = "tempXXXl\\ate";
|
||||
|
||||
#[cfg(not(windows))]
|
||||
const TMPDIR: &str = "TMPDIR";
|
||||
#[cfg(windows)]
|
||||
const TMPDIR: &str = "TMP";
|
||||
|
||||
#[test]
|
||||
fn test_mktemp_mktemp() {
|
||||
|
@ -122,7 +125,8 @@ fn test_mktemp_mktemp_t() {
|
|||
.arg(TEST_TEMPLATE8)
|
||||
.fails()
|
||||
.no_stdout()
|
||||
.stderr_contains("suffix cannot contain any path separators");
|
||||
.stderr_contains("invalid suffix")
|
||||
.stderr_contains("contains directory separator");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -386,7 +390,7 @@ fn test_mktemp_tmpdir_one_arg() {
|
|||
let scene = TestScenario::new(util_name!());
|
||||
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.ucmd_keepenv()
|
||||
.arg("--tmpdir")
|
||||
.arg("apt-key-gpghome.XXXXXXXXXX")
|
||||
.succeeds();
|
||||
|
@ -399,7 +403,7 @@ fn test_mktemp_directory_tmpdir() {
|
|||
let scene = TestScenario::new(util_name!());
|
||||
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.ucmd_keepenv()
|
||||
.arg("--directory")
|
||||
.arg("--tmpdir")
|
||||
.arg("apt-key-gpghome.XXXXXXXXXX")
|
||||
|
|
|
@ -614,7 +614,7 @@ fn test_mv_overwrite_nonempty_dir() {
|
|||
// Not same error as GNU; the error message is a rust builtin
|
||||
// TODO: test (and implement) correct error message (or at least decide whether to do so)
|
||||
// Current: "mv: couldn't rename path (Directory not empty; from=a; to=b)"
|
||||
// GNU: "mv: cannot move ‘a’ to ‘b’: Directory not empty"
|
||||
// GNU: "mv: cannot move 'a' to 'b': Directory not empty"
|
||||
|
||||
// Verbose output for the move should not be shown on failure
|
||||
let result = ucmd.arg("-vT").arg(dir_a).arg(dir_b).fails();
|
||||
|
@ -638,7 +638,7 @@ fn test_mv_backup_dir() {
|
|||
.arg(dir_b)
|
||||
.succeeds()
|
||||
.stdout_only(format!(
|
||||
"‘{}’ -> ‘{}’ (backup: ‘{}~’)\n",
|
||||
"'{}' -> '{}' (backup: '{}~')\n",
|
||||
dir_a, dir_b, dir_b
|
||||
));
|
||||
|
||||
|
@ -672,7 +672,7 @@ fn test_mv_errors() {
|
|||
|
||||
// $ at.touch file && at.mkdir dir
|
||||
// $ mv -T file dir
|
||||
// err == mv: cannot overwrite directory ‘dir’ with non-directory
|
||||
// err == mv: cannot overwrite directory 'dir' with non-directory
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-T")
|
||||
|
@ -680,13 +680,13 @@ fn test_mv_errors() {
|
|||
.arg(dir)
|
||||
.fails()
|
||||
.stderr_is(format!(
|
||||
"mv: cannot overwrite directory ‘{}’ with non-directory\n",
|
||||
"mv: cannot overwrite directory '{}' with non-directory\n",
|
||||
dir
|
||||
));
|
||||
|
||||
// $ at.mkdir dir && at.touch file
|
||||
// $ mv dir file
|
||||
// err == mv: cannot overwrite non-directory ‘file’ with directory ‘dir’
|
||||
// err == mv: cannot overwrite non-directory 'file' with directory 'dir'
|
||||
assert!(!scene
|
||||
.ucmd()
|
||||
.arg(dir)
|
||||
|
@ -713,7 +713,7 @@ fn test_mv_verbose() {
|
|||
.arg(file_a)
|
||||
.arg(file_b)
|
||||
.succeeds()
|
||||
.stdout_only(format!("‘{}’ -> ‘{}’\n", file_a, file_b));
|
||||
.stdout_only(format!("'{}' -> '{}'\n", file_a, file_b));
|
||||
|
||||
at.touch(file_a);
|
||||
scene
|
||||
|
@ -723,12 +723,13 @@ fn test_mv_verbose() {
|
|||
.arg(file_b)
|
||||
.succeeds()
|
||||
.stdout_only(format!(
|
||||
"‘{}’ -> ‘{}’ (backup: ‘{}~’)\n",
|
||||
"'{}' -> '{}' (backup: '{}~')\n",
|
||||
file_a, file_b, file_b
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "linux")] // mkdir does not support -m on windows. Freebsd doesn't return a permission error either.
|
||||
fn test_mv_permission_error() {
|
||||
let scene = TestScenario::new("mkdir");
|
||||
let folder1 = "bar";
|
||||
|
@ -738,12 +739,11 @@ fn test_mv_permission_error() {
|
|||
scene.ucmd().arg("-m777").arg(folder2).succeeds();
|
||||
|
||||
scene
|
||||
.cmd_keepenv(util_name!())
|
||||
.ccmd("mv")
|
||||
.arg(folder2)
|
||||
.arg(folder_to_move)
|
||||
.run()
|
||||
.stderr_str()
|
||||
.ends_with("Permission denied");
|
||||
.fails()
|
||||
.stderr_contains("Permission denied");
|
||||
}
|
||||
|
||||
// Todo:
|
||||
|
@ -756,5 +756,5 @@ fn test_mv_permission_error() {
|
|||
// -r--r--r-- 1 user user 0 okt 25 11:21 b
|
||||
// $
|
||||
// $ mv -v a b
|
||||
// mv: try to overwrite ‘b’, overriding mode 0444 (r--r--r--)? y
|
||||
// ‘a’ -> ‘b’
|
||||
// mv: try to overwrite 'b', overriding mode 0444 (r--r--r--)? y
|
||||
// 'a' -> 'b'
|
||||
|
|
|
@ -35,7 +35,7 @@ fn test_from_iec_i_requires_suffix() {
|
|||
new_ucmd!()
|
||||
.args(&["--from=iec-i", "1024"])
|
||||
.fails()
|
||||
.stderr_is("numfmt: missing 'i' suffix in input: ‘1024’ (e.g Ki/Mi/Gi)");
|
||||
.stderr_is("numfmt: missing 'i' suffix in input: '1024' (e.g Ki/Mi/Gi)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -123,7 +123,7 @@ fn test_header_error_if_non_numeric() {
|
|||
new_ucmd!()
|
||||
.args(&["--header=two"])
|
||||
.run()
|
||||
.stderr_is("numfmt: invalid header value ‘two’");
|
||||
.stderr_is("numfmt: invalid header value 'two'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -131,7 +131,7 @@ fn test_header_error_if_0() {
|
|||
new_ucmd!()
|
||||
.args(&["--header=0"])
|
||||
.run()
|
||||
.stderr_is("numfmt: invalid header value ‘0’");
|
||||
.stderr_is("numfmt: invalid header value '0'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -139,7 +139,7 @@ fn test_header_error_if_negative() {
|
|||
new_ucmd!()
|
||||
.args(&["--header=-3"])
|
||||
.run()
|
||||
.stderr_is("numfmt: invalid header value ‘-3’");
|
||||
.stderr_is("numfmt: invalid header value '-3'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -187,7 +187,7 @@ fn test_should_report_invalid_empty_number_on_empty_stdin() {
|
|||
.args(&["--from=auto"])
|
||||
.pipe_in("\n")
|
||||
.run()
|
||||
.stderr_is("numfmt: invalid number: ‘’\n");
|
||||
.stderr_is("numfmt: invalid number: ''\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -196,7 +196,7 @@ fn test_should_report_invalid_empty_number_on_blank_stdin() {
|
|||
.args(&["--from=auto"])
|
||||
.pipe_in(" \t \n")
|
||||
.run()
|
||||
.stderr_is("numfmt: invalid number: ‘’\n");
|
||||
.stderr_is("numfmt: invalid number: ''\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -205,14 +205,14 @@ fn test_should_report_invalid_suffix_on_stdin() {
|
|||
.args(&["--from=auto"])
|
||||
.pipe_in("1k")
|
||||
.run()
|
||||
.stderr_is("numfmt: invalid suffix in input: ‘1k’\n");
|
||||
.stderr_is("numfmt: invalid suffix in input: '1k'\n");
|
||||
|
||||
// GNU numfmt reports this one as “invalid number”
|
||||
new_ucmd!()
|
||||
.args(&["--from=auto"])
|
||||
.pipe_in("NaN")
|
||||
.run()
|
||||
.stderr_is("numfmt: invalid suffix in input: ‘NaN’\n");
|
||||
.stderr_is("numfmt: invalid suffix in input: 'NaN'\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -222,7 +222,7 @@ fn test_should_report_invalid_number_with_interior_junk() {
|
|||
.args(&["--from=auto"])
|
||||
.pipe_in("1x0K")
|
||||
.run()
|
||||
.stderr_is("numfmt: invalid number: ‘1x0K’\n");
|
||||
.stderr_is("numfmt: invalid number: '1x0K'\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -461,7 +461,7 @@ fn test_delimiter_overrides_whitespace_separator() {
|
|||
.args(&["-d,"])
|
||||
.pipe_in("1 234,56")
|
||||
.fails()
|
||||
.stderr_is("numfmt: invalid number: ‘1 234’\n");
|
||||
.stderr_is("numfmt: invalid number: '1 234'\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -481,3 +481,27 @@ fn test_delimiter_with_padding_and_fields() {
|
|||
.succeeds()
|
||||
.stdout_only(" 1.0K| 2.0K\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_round() {
|
||||
for (method, exp) in &[
|
||||
("from-zero", ["9.1K", "-9.1K", "9.1K", "-9.1K"]),
|
||||
("towards-zero", ["9.0K", "-9.0K", "9.0K", "-9.0K"]),
|
||||
("up", ["9.1K", "-9.0K", "9.1K", "-9.0K"]),
|
||||
("down", ["9.0K", "-9.1K", "9.0K", "-9.1K"]),
|
||||
("nearest", ["9.0K", "-9.0K", "9.1K", "-9.1K"]),
|
||||
] {
|
||||
new_ucmd!()
|
||||
.args(&[
|
||||
"--to=si",
|
||||
&format!("--round={}", method),
|
||||
"--",
|
||||
"9001",
|
||||
"-9001",
|
||||
"9099",
|
||||
"-9099",
|
||||
])
|
||||
.succeeds()
|
||||
.stdout_only(exp.join("\n") + "\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,7 +106,7 @@ fn expected_result(args: &[&str]) -> String {
|
|||
#[allow(clippy::needless_borrow)]
|
||||
TestScenario::new(&util_name)
|
||||
.cmd_keepenv(util_name)
|
||||
.env("LANGUAGE", "C")
|
||||
.env("LC_ALL", "C")
|
||||
.args(args)
|
||||
.succeeds()
|
||||
.stdout_move_str()
|
||||
|
|
|
@ -22,6 +22,7 @@ fn file_last_modified_time(ucmd: &UCommand, path: &str) -> String {
|
|||
}
|
||||
|
||||
fn all_minutes(from: DateTime<Local>, to: DateTime<Local>) -> Vec<String> {
|
||||
let to = to + Duration::minutes(1);
|
||||
const FORMAT: &str = "%b %d %H:%M %Y";
|
||||
let mut vec = vec![];
|
||||
let mut current = from;
|
||||
|
|
|
@ -28,7 +28,8 @@ fn test_helper(file_name: &str, possible_args: &[&str]) {
|
|||
fn test_buffer_sizes() {
|
||||
let buffer_sizes = ["0", "50K", "50k", "1M", "100M"];
|
||||
for buffer_size in &buffer_sizes {
|
||||
new_ucmd!()
|
||||
TestScenario::new(util_name!())
|
||||
.ucmd_keepenv()
|
||||
.arg("-n")
|
||||
.arg("-S")
|
||||
.arg(buffer_size)
|
||||
|
@ -40,7 +41,8 @@ fn test_buffer_sizes() {
|
|||
{
|
||||
let buffer_sizes = ["1000G", "10T"];
|
||||
for buffer_size in &buffer_sizes {
|
||||
new_ucmd!()
|
||||
TestScenario::new(util_name!())
|
||||
.ucmd_keepenv()
|
||||
.arg("-n")
|
||||
.arg("-S")
|
||||
.arg(buffer_size)
|
||||
|
@ -125,11 +127,7 @@ fn test_months_whitespace() {
|
|||
|
||||
#[test]
|
||||
fn test_version_empty_lines() {
|
||||
new_ucmd!()
|
||||
.arg("-V")
|
||||
.arg("version-empty-lines.txt")
|
||||
.succeeds()
|
||||
.stdout_is("\n\n\n\n\n\n\n1.2.3-alpha\n1.2.3-alpha2\n\t\t\t1.12.4\n11.2.3\n");
|
||||
test_helper("version-empty-lines", &["-V", "--version-sort"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -454,10 +452,20 @@ fn test_human_block_sizes2() {
|
|||
.arg(human_numeric_sort_param)
|
||||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_only("-8T\n0.8M\n8981K\n21G\n909991M\n");
|
||||
.stdout_only("-8T\n8981K\n0.8M\n909991M\n21G\n");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_human_numeric_zero_stable() {
|
||||
let input = "0M\n0K\n-0K\n-P\n-0M\n";
|
||||
new_ucmd!()
|
||||
.arg("-hs")
|
||||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_only(input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_month_default2() {
|
||||
for month_sort_param in &["-M", "--month-sort", "--sort=month"] {
|
||||
|
@ -877,7 +885,8 @@ fn test_compress() {
|
|||
|
||||
#[test]
|
||||
fn test_compress_fail() {
|
||||
new_ucmd!()
|
||||
TestScenario::new(util_name!())
|
||||
.ucmd_keepenv()
|
||||
.args(&[
|
||||
"ext_sort.txt",
|
||||
"-n",
|
||||
|
@ -892,7 +901,8 @@ fn test_compress_fail() {
|
|||
|
||||
#[test]
|
||||
fn test_merge_batches() {
|
||||
new_ucmd!()
|
||||
TestScenario::new(util_name!())
|
||||
.ucmd_keepenv()
|
||||
.args(&["ext_sort.txt", "-n", "-S", "150b"])
|
||||
.succeeds()
|
||||
.stdout_only_fixture("ext_sort.expected");
|
||||
|
@ -900,7 +910,8 @@ fn test_merge_batches() {
|
|||
|
||||
#[test]
|
||||
fn test_merge_batch_size() {
|
||||
new_ucmd!()
|
||||
TestScenario::new(util_name!())
|
||||
.ucmd_keepenv()
|
||||
.arg("--batch-size=2")
|
||||
.arg("-m")
|
||||
.arg("--unique")
|
||||
|
@ -926,3 +937,17 @@ fn test_sigpipe_panic() {
|
|||
Ok(String::new())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_conflict_check_out() {
|
||||
let check_flags = ["-c=silent", "-c=quiet", "-c=diagnose-first", "-c", "-C"];
|
||||
for check_flag in &check_flags {
|
||||
new_ucmd!()
|
||||
.arg(check_flag)
|
||||
.arg("-o=/dev/null")
|
||||
.fails()
|
||||
.stderr_contains(
|
||||
"error: The argument '--output <FILENAME>' cannot be used with '--check",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -309,7 +309,7 @@ fn test_split_lines_number() {
|
|||
.args(&["--lines", "2fb", "file"])
|
||||
.fails()
|
||||
.code_is(1)
|
||||
.stderr_only("split: invalid number of lines: ‘2fb’");
|
||||
.stderr_only("split: invalid number of lines: '2fb'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -318,13 +318,13 @@ fn test_split_invalid_bytes_size() {
|
|||
.args(&["-b", "1024R"])
|
||||
.fails()
|
||||
.code_is(1)
|
||||
.stderr_only("split: invalid number of bytes: ‘1024R’");
|
||||
.stderr_only("split: invalid number of bytes: '1024R'");
|
||||
#[cfg(not(target_pointer_width = "128"))]
|
||||
new_ucmd!()
|
||||
.args(&["-b", "1Y"])
|
||||
.fails()
|
||||
.code_is(1)
|
||||
.stderr_only("split: invalid number of bytes: ‘1Y’: Value too large for defined data type");
|
||||
.stderr_only("split: invalid number of bytes: '1Y': Value too large for defined data type");
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
{
|
||||
let sizes = ["1000G", "10T"];
|
||||
|
@ -334,7 +334,7 @@ fn test_split_invalid_bytes_size() {
|
|||
.fails()
|
||||
.code_is(1)
|
||||
.stderr_only(format!(
|
||||
"split: invalid number of bytes: ‘{}’: Value too large for defined data type",
|
||||
"split: invalid number of bytes: '{}': Value too large for defined data type",
|
||||
size
|
||||
));
|
||||
}
|
||||
|
|
|
@ -317,7 +317,7 @@ fn expected_result(args: &[&str]) -> String {
|
|||
#[allow(clippy::needless_borrow)]
|
||||
TestScenario::new(&util_name)
|
||||
.cmd_keepenv(util_name)
|
||||
.env("LANGUAGE", "C")
|
||||
.env("LC_ALL", "C")
|
||||
.args(args)
|
||||
.succeeds()
|
||||
.stdout_move_str()
|
||||
|
|
|
@ -63,12 +63,12 @@ fn test_stdbuf_invalid_mode_fails() {
|
|||
.args(&[*option, "1024R", "head"])
|
||||
.fails()
|
||||
.code_is(125)
|
||||
.stderr_only("stdbuf: invalid mode ‘1024R’");
|
||||
.stderr_only("stdbuf: invalid mode '1024R'");
|
||||
#[cfg(not(target_pointer_width = "128"))]
|
||||
new_ucmd!()
|
||||
.args(&[*option, "1Y", "head"])
|
||||
.fails()
|
||||
.code_is(125)
|
||||
.stderr_contains("stdbuf: invalid mode ‘1Y’: Value too large for defined data type");
|
||||
.stderr_contains("stdbuf: invalid mode '1Y': Value too large for defined data type");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -364,21 +364,21 @@ fn test_tail_invalid_num() {
|
|||
new_ucmd!()
|
||||
.args(&["-c", "1024R", "emptyfile.txt"])
|
||||
.fails()
|
||||
.stderr_is("tail: invalid number of bytes: ‘1024R’");
|
||||
.stderr_is("tail: invalid number of bytes: '1024R'");
|
||||
new_ucmd!()
|
||||
.args(&["-n", "1024R", "emptyfile.txt"])
|
||||
.fails()
|
||||
.stderr_is("tail: invalid number of lines: ‘1024R’");
|
||||
.stderr_is("tail: invalid number of lines: '1024R'");
|
||||
#[cfg(not(target_pointer_width = "128"))]
|
||||
new_ucmd!()
|
||||
.args(&["-c", "1Y", "emptyfile.txt"])
|
||||
.fails()
|
||||
.stderr_is("tail: invalid number of bytes: ‘1Y’: Value too large for defined data type");
|
||||
.stderr_is("tail: invalid number of bytes: '1Y': Value too large for defined data type");
|
||||
#[cfg(not(target_pointer_width = "128"))]
|
||||
new_ucmd!()
|
||||
.args(&["-n", "1Y", "emptyfile.txt"])
|
||||
.fails()
|
||||
.stderr_is("tail: invalid number of lines: ‘1Y’: Value too large for defined data type");
|
||||
.stderr_is("tail: invalid number of lines: '1Y': Value too large for defined data type");
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
{
|
||||
let sizes = ["1000G", "10T"];
|
||||
|
@ -388,7 +388,7 @@ fn test_tail_invalid_num() {
|
|||
.fails()
|
||||
.code_is(1)
|
||||
.stderr_only(format!(
|
||||
"tail: invalid number of bytes: ‘{}’: Value too large for defined data type",
|
||||
"tail: invalid number of bytes: '{}': Value too large for defined data type",
|
||||
size
|
||||
));
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ fn test_dangling_string_comparison_is_error() {
|
|||
.args(&["missing_something", "="])
|
||||
.run()
|
||||
.status_code(2)
|
||||
.stderr_is("test: missing argument after ‘=’");
|
||||
.stderr_is("test: missing argument after '='");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -265,7 +265,7 @@ fn test_float_inequality_is_error() {
|
|||
.args(&["123.45", "-ge", "6"])
|
||||
.run()
|
||||
.status_code(2)
|
||||
.stderr_is("test: invalid integer ‘123.45’");
|
||||
.stderr_is("test: invalid integer '123.45'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -283,7 +283,7 @@ fn test_invalid_utf8_integer_compare() {
|
|||
|
||||
cmd.run()
|
||||
.status_code(2)
|
||||
.stderr_is("test: invalid integer ‘fo<EFBFBD>o’");
|
||||
.stderr_is("test: invalid integer 'fo<66>o'");
|
||||
|
||||
let mut cmd = new_ucmd!();
|
||||
cmd.raw.arg(arg);
|
||||
|
@ -291,7 +291,7 @@ fn test_invalid_utf8_integer_compare() {
|
|||
|
||||
cmd.run()
|
||||
.status_code(2)
|
||||
.stderr_is("test: invalid integer ‘fo<EFBFBD>o’");
|
||||
.stderr_is("test: invalid integer 'fo<66>o'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -674,7 +674,7 @@ fn test_erroneous_parenthesized_expression() {
|
|||
.args(&["a", "!=", "(", "b", "-a", "b", ")", "!=", "c"])
|
||||
.run()
|
||||
.status_code(2)
|
||||
.stderr_is("test: extra argument ‘b’");
|
||||
.stderr_is("test: extra argument 'b'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -690,3 +690,31 @@ fn test_or_as_filename() {
|
|||
fn test_string_length_and_nothing() {
|
||||
new_ucmd!().args(&["-n", "a", "-a"]).run().status_code(2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bracket_syntax_success() {
|
||||
let scenario = TestScenario::new("[");
|
||||
let mut ucmd = scenario.ucmd();
|
||||
|
||||
ucmd.args(&["1", "-eq", "1", "]"]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bracket_syntax_failure() {
|
||||
let scenario = TestScenario::new("[");
|
||||
let mut ucmd = scenario.ucmd();
|
||||
|
||||
ucmd.args(&["1", "-eq", "2", "]"]).run().status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bracket_syntax_missing_right_bracket() {
|
||||
let scenario = TestScenario::new("[");
|
||||
let mut ucmd = scenario.ucmd();
|
||||
|
||||
// Missing closing bracket takes precedence over other possible errors.
|
||||
ucmd.args(&["1", "-eq"])
|
||||
.run()
|
||||
.status_code(2)
|
||||
.stderr_is("[: missing ']'");
|
||||
}
|
||||
|
|
|
@ -249,7 +249,7 @@ fn test_size_and_reference() {
|
|||
|
||||
#[test]
|
||||
fn test_error_filename_only() {
|
||||
// truncate: you must specify either ‘--size’ or ‘--reference’
|
||||
// truncate: you must specify either '--size' or '--reference'
|
||||
new_ucmd!().args(&["file"]).fails().stderr_contains(
|
||||
"error: The following required arguments were not provided:
|
||||
--reference <RFILE>
|
||||
|
@ -262,15 +262,15 @@ fn test_invalid_numbers() {
|
|||
new_ucmd!()
|
||||
.args(&["-s", "0X", "file"])
|
||||
.fails()
|
||||
.stderr_contains("Invalid number: ‘0X’");
|
||||
.stderr_contains("Invalid number: '0X'");
|
||||
new_ucmd!()
|
||||
.args(&["-s", "0XB", "file"])
|
||||
.fails()
|
||||
.stderr_contains("Invalid number: ‘0XB’");
|
||||
.stderr_contains("Invalid number: '0XB'");
|
||||
new_ucmd!()
|
||||
.args(&["-s", "0B", "file"])
|
||||
.fails()
|
||||
.stderr_contains("Invalid number: ‘0B’");
|
||||
.stderr_contains("Invalid number: '0B'");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -299,13 +299,13 @@ fn test_truncate_bytes_size() {
|
|||
.args(&["--size", "1024R", "file"])
|
||||
.fails()
|
||||
.code_is(1)
|
||||
.stderr_only("truncate: Invalid number: ‘1024R’");
|
||||
.stderr_only("truncate: Invalid number: '1024R'");
|
||||
#[cfg(not(target_pointer_width = "128"))]
|
||||
new_ucmd!()
|
||||
.args(&["--size", "1Y", "file"])
|
||||
.fails()
|
||||
.code_is(1)
|
||||
.stderr_only("truncate: Invalid number: ‘1Y’: Value too large for defined data type");
|
||||
.stderr_only("truncate: Invalid number: '1Y': Value too large for defined data type");
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
{
|
||||
let sizes = ["1000G", "10T"];
|
||||
|
@ -315,7 +315,7 @@ fn test_truncate_bytes_size() {
|
|||
.fails()
|
||||
.code_is(1)
|
||||
.stderr_only(format!(
|
||||
"truncate: Invalid number: ‘{}’: Value too large for defined data type",
|
||||
"truncate: Invalid number: '{}': Value too large for defined data type",
|
||||
size
|
||||
));
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ fn test_users_check_name() {
|
|||
#[allow(clippy::needless_borrow)]
|
||||
let expected = TestScenario::new(&util_name)
|
||||
.cmd_keepenv(util_name)
|
||||
.env("LANGUAGE", "C")
|
||||
.env("LC_ALL", "C")
|
||||
.succeeds()
|
||||
.stdout_move_str();
|
||||
|
||||
|
|
|
@ -158,13 +158,12 @@ fn test_users() {
|
|||
let mut v_actual: Vec<&str> = actual.split_whitespace().collect();
|
||||
let mut v_expect: Vec<&str> = expect.split_whitespace().collect();
|
||||
|
||||
// TODO: `--users` differs from GNU's output on macOS
|
||||
// Diff < left / right > :
|
||||
// <"runner console 2021-05-20 22:03 00:08 196\n"
|
||||
// >"runner console 2021-05-20 22:03 old 196\n"
|
||||
// TODO: `--users` sometimes differs from GNU's output on macOS (race condition?)
|
||||
// actual: "runner console Jun 23 06:37 00:34 196\n"
|
||||
// expect: "runner console Jun 23 06:37 old 196\n"
|
||||
if cfg!(target_os = "macos") {
|
||||
v_actual.remove(4);
|
||||
v_expect.remove(4);
|
||||
v_actual.remove(5);
|
||||
v_expect.remove(5);
|
||||
}
|
||||
|
||||
assert_eq!(v_actual, v_expect);
|
||||
|
@ -242,7 +241,7 @@ fn expected_result(args: &[&str]) -> String {
|
|||
#[allow(clippy::needless_borrow)]
|
||||
TestScenario::new(&util_name)
|
||||
.cmd_keepenv(util_name)
|
||||
.env("LANGUAGE", "C")
|
||||
.env("LC_ALL", "C")
|
||||
.args(args)
|
||||
.succeeds()
|
||||
.stdout_move_str()
|
||||
|
|
1
tests/fixtures/du/subdir/deeper/deeper_dir/deeper_words.txt
vendored
Normal file
1
tests/fixtures/du/subdir/deeper/deeper_dir/deeper_words.txt
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
hello world!
|
|
@ -1,3 +1,4 @@
|
|||
0K
|
||||
K
|
||||
844K
|
||||
981K
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
0K
|
||||
__
|
||||
__
|
||||
K
|
||||
^ no match for key
|
||||
_
|
||||
|
|
3
tests/fixtures/sort/human_block_sizes.txt
vendored
3
tests/fixtures/sort/human_block_sizes.txt
vendored
|
@ -9,4 +9,5 @@
|
|||
844K
|
||||
981K
|
||||
13M
|
||||
K
|
||||
K
|
||||
0K
|
|
@ -8,4 +8,8 @@
|
|||
1.2.3-alpha
|
||||
1.2.3-alpha2
|
||||
11.2.3
|
||||
bar2
|
||||
bar2.0.0
|
||||
foo0.1
|
||||
foo1.0
|
||||
1.12.4
|
||||
|
|
45
tests/fixtures/sort/version-empty-lines.expected.debug
vendored
Normal file
45
tests/fixtures/sort/version-empty-lines.expected.debug
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
|
||||
^ no match for key
|
||||
^ no match for key
|
||||
|
||||
^ no match for key
|
||||
^ no match for key
|
||||
|
||||
^ no match for key
|
||||
^ no match for key
|
||||
|
||||
^ no match for key
|
||||
^ no match for key
|
||||
|
||||
^ no match for key
|
||||
^ no match for key
|
||||
|
||||
^ no match for key
|
||||
^ no match for key
|
||||
|
||||
^ no match for key
|
||||
^ no match for key
|
||||
1.2.3-alpha
|
||||
___________
|
||||
___________
|
||||
1.2.3-alpha2
|
||||
____________
|
||||
____________
|
||||
11.2.3
|
||||
______
|
||||
______
|
||||
bar2
|
||||
____
|
||||
____
|
||||
bar2.0.0
|
||||
________
|
||||
________
|
||||
foo0.1
|
||||
______
|
||||
______
|
||||
foo1.0
|
||||
______
|
||||
______
|
||||
>>>1.12.4
|
||||
_________
|
||||
_________
|
4
tests/fixtures/sort/version-empty-lines.txt
vendored
4
tests/fixtures/sort/version-empty-lines.txt
vendored
|
@ -9,3 +9,7 @@
|
|||
|
||||
|
||||
1.12.4
|
||||
foo1.0
|
||||
foo0.1
|
||||
bar2.0.0
|
||||
bar2
|
Loading…
Add table
Add a link
Reference in a new issue