1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-29 12:07:46 +00:00

Merge branch 'master' into ls/fix_backslash_escape

This commit is contained in:
Terts Diepraam 2021-04-21 12:06:54 +02:00
commit fd54614130
90 changed files with 2354 additions and 1038 deletions

View file

@ -26,7 +26,7 @@ fn test_no_options() {
}
#[test]
#[cfg(unix)]
#[cfg(any(target_vendor = "apple", target_os = "linux", target_os = "android"))]
fn test_no_options_big_input() {
for &n in &[
0,

View file

@ -357,7 +357,8 @@ fn test_chmod_symlink_non_existing_file() {
at.symlink_file(non_existing, test_symlink);
// this cannot succeed since the symbolic link dangles
scene.ucmd()
scene
.ucmd()
.arg("755")
.arg("-v")
.arg(test_symlink)
@ -367,7 +368,8 @@ fn test_chmod_symlink_non_existing_file() {
.stderr_contains(expected_stderr);
// this should be the same than with just '-v' but without stderr
scene.ucmd()
scene
.ucmd()
.arg("755")
.arg("-v")
.arg("-f")
@ -394,7 +396,8 @@ fn test_chmod_symlink_non_existing_file_recursive() {
);
// this should succeed
scene.ucmd()
scene
.ucmd()
.arg("-R")
.arg("755")
.arg(test_directory)
@ -408,7 +411,8 @@ fn test_chmod_symlink_non_existing_file_recursive() {
);
// '-v': this should succeed without stderr
scene.ucmd()
scene
.ucmd()
.arg("-R")
.arg("-v")
.arg("755")
@ -418,7 +422,8 @@ fn test_chmod_symlink_non_existing_file_recursive() {
.no_stderr();
// '-vf': this should be the same than with just '-v'
scene.ucmd()
scene
.ucmd()
.arg("-R")
.arg("-v")
.arg("-f")

View file

@ -4,6 +4,34 @@ use rust_users::get_effective_uid;
extern crate chown;
// Apparently some CI environments have configuration issues, e.g. with 'whoami' and 'id'.
// If we are running inside the CI and "needle" is in "stderr" skipping this test is
// considered okay. If we are not inside the CI this calls assert!(result.success).
//
// From the Logs: "Build (ubuntu-18.04, x86_64-unknown-linux-gnu, feat_os_unix, use-cross)"
//
// stderr: "whoami: cannot find name for user ID 1001"
// TODO: Maybe `adduser --uid 1001 username` can put things right?
//
// stderr: "id: cannot find name for group ID 116"
// stderr: "thread 'main' panicked at 'called `Result::unwrap()` on an `Err`
// value: Custom { kind: NotFound, error: "No such id: 1001" }',
// /project/src/uucore/src/lib/features/perms.rs:176:44"
//
fn skipping_test_is_okay(result: &CmdResult, needle: &str) -> bool {
if !result.succeeded() {
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
if is_ci() && result.stderr_str().contains(needle) {
println!("test skipped:");
return true;
} else {
result.success();
}
}
false
}
#[cfg(test)]
mod test_passgrp {
use super::chown::entries::{gid2grp, grp2gid, uid2usr, usr2uid};
@ -49,116 +77,193 @@ fn test_invalid_option() {
}
#[test]
fn test_chown_myself() {
fn test_chown_only_owner() {
// test chown username file.txt
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let result = scene.cmd("whoami").run();
if is_ci() && result.stderr_str().contains("No such user/group") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
if skipping_test_is_okay(&result, "whoami: cannot find name for user ID") {
return;
}
println!("results {}", result.stdout_str());
let username = result.stdout_str().trim_end();
let (at, mut ucmd) = at_and_ucmd!();
let file1 = "test_install_target_dir_file_a1";
let user_name = String::from(result.stdout_str().trim());
assert!(!user_name.is_empty());
let file1 = "test_chown_file1";
at.touch(file1);
let result = ucmd.arg(username).arg(file1).run();
println!("results stdout {}", result.stdout_str());
println!("results stderr {}", result.stderr_str());
if is_ci() && result.stderr_str().contains("invalid user") {
// In the CI, some server are failing to return id.
// As seems to be a configuration issue, ignoring it
return;
}
assert!(result.success);
}
#[test]
fn test_chown_myself_second() {
// test chown username: file.txt
let scene = TestScenario::new(util_name!());
let result = scene.cmd("whoami").run();
if is_ci() && result.stderr_str().contains("No such user/group") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
return;
}
println!("results {}", result.stdout_str());
let (at, mut ucmd) = at_and_ucmd!();
let file1 = "test_install_target_dir_file_a1";
at.touch(file1);
let result = ucmd
.arg(result.stdout_str().trim_end().to_owned() + ":")
// since only superuser can change owner, we have to change from ourself to ourself
let result = scene
.ucmd()
.arg(user_name)
.arg("--verbose")
.arg(file1)
.run();
result.stderr_contains(&"retained as");
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
assert!(result.success);
// try to change to another existing user, e.g. 'root'
scene
.ucmd()
.arg("root")
.arg("--verbose")
.arg(file1)
.fails()
.stderr_contains(&"failed to change");
}
#[test]
fn test_chown_myself_group() {
// test chown username:group file.txt
fn test_chown_only_owner_colon() {
// test chown username: file.txt
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let result = scene.cmd("whoami").run();
if is_ci() && result.stderr_str().contains("No such user/group") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
if skipping_test_is_okay(&result, "whoami: cannot find name for user ID") {
return;
}
println!("user name = {}", result.stdout_str());
let username = result.stdout_str().trim_end();
let user_name = String::from(result.stdout_str().trim());
assert!(!user_name.is_empty());
let file1 = "test_chown_file1";
at.touch(file1);
scene
.ucmd()
.arg(format!("{}:", user_name))
.arg("--verbose")
.arg(file1)
.succeeds()
.stderr_contains(&"retained as");
scene
.ucmd()
.arg("root:")
.arg("--verbose")
.arg(file1)
.fails()
.stderr_contains(&"failed to change");
}
#[test]
fn test_chown_only_colon() {
// test chown : file.txt
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let file1 = "test_chown_file1";
at.touch(file1);
// expected:
// $ chown -v : file.txt 2>out_err ; echo $? ; cat out_err
// ownership of 'file.txt' retained
// 0
let result = scene.ucmd().arg(":").arg("--verbose").arg(file1).run();
if skipping_test_is_okay(&result, "No such id") {
return;
}
result.stderr_contains(&"retained as"); // TODO: verbose is not printed to stderr in GNU chown
// test chown : file.txt
// expected:
// $ chown -v :: file.txt 2>out_err ; echo $? ; cat out_err
// 1
// chown: invalid group: ::
scene
.ucmd()
.arg("::")
.arg("--verbose")
.arg(file1)
.fails()
.stderr_contains(&"invalid group: ::");
}
#[test]
fn test_chown_failed_stdout() {
// test chown root file.txt
// TODO: implement once output "failed to change" to stdout is fixed
// expected:
// $ chown -v root file.txt 2>out_err ; echo $? ; cat out_err
// failed to change ownership of 'file.txt' from jhs to root
// 1
// chown: changing ownership of 'file.txt': Operation not permitted
}
#[test]
fn test_chown_owner_group() {
// 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 is_ci() && result.stderr_str().contains("No such user/group") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
if skipping_test_is_okay(&result, "id: cannot find name for group ID") {
return;
}
println!("group name = {}", result.stdout_str());
let group = result.stdout_str().trim_end();
let group_name = String::from(result.stdout_str().trim());
assert!(!group_name.is_empty());
let (at, mut ucmd) = at_and_ucmd!();
let file1 = "test_install_target_dir_file_a1";
let perm = username.to_owned() + ":" + group;
at.touch(file1);
let result = ucmd.arg(perm).arg(file1).run();
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
if is_ci() && result.stderr_str().contains("chown: invalid group:") {
// With some Ubuntu into the CI, we can get this answer
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;
}
assert!(result.success);
result.stderr_contains(&"retained as");
// TODO: on macos group name is not recognized correctly: "chown: invalid group: 'root:root'
#[cfg(any(windows, all(unix, not(target_os = "macos"))))]
scene
.ucmd()
.arg("root:root")
.arg("--verbose")
.arg(file1)
.fails()
.stderr_contains(&"failed to change");
}
#[test]
// TODO: on macos group name is not recognized correctly: "chown: invalid group: ':groupname'
#[cfg(any(windows, all(unix, not(target_os = "macos"))))]
fn test_chown_only_group() {
// test chown :group file.txt
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let result = scene.cmd("whoami").run();
if is_ci() && result.stderr_str().contains("No such user/group") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
if skipping_test_is_okay(&result, "whoami: cannot find name for user ID") {
return;
}
println!("results {}", result.stdout_str());
let user_name = String::from(result.stdout_str().trim());
assert!(!user_name.is_empty());
let (at, mut ucmd) = at_and_ucmd!();
let file1 = "test_install_target_dir_file_a1";
let perm = ":".to_owned() + result.stdout_str().trim_end();
let file1 = "test_chown_file1";
at.touch(file1);
let result = ucmd.arg(perm).arg(file1).run();
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
let result = scene
.ucmd()
.arg(format!(":{}", user_name))
.arg("--verbose")
.arg(file1)
.run();
if is_ci() && result.stderr_str().contains("Operation not permitted") {
// With ubuntu with old Rust in the CI, we can get an error
return;
@ -167,221 +272,232 @@ fn test_chown_only_group() {
// With mac into the CI, we can get this answer
return;
}
assert!(result.success);
result.stderr_contains(&"retained as");
result.success();
scene
.ucmd()
.arg(":root")
.arg("--verbose")
.arg(file1)
.fails()
.stderr_contains(&"failed to change");
}
#[test]
fn test_chown_only_id() {
fn test_chown_only_user_id() {
// test chown 1111 file.txt
let result = TestScenario::new("id").ucmd_keepenv().arg("-u").run();
if is_ci() && result.stderr_str().contains("No such user/group") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let result = scene.cmd_keepenv("id").arg("-u").run();
if skipping_test_is_okay(&result, "id: cannot find name for group ID") {
return;
}
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
let id = String::from(result.stdout_str().trim());
let (at, mut ucmd) = at_and_ucmd!();
let file1 = "test_install_target_dir_file_a1";
let user_id = String::from(result.stdout_str().trim());
assert!(!user_id.is_empty());
let file1 = "test_chown_file1";
at.touch(file1);
let result = ucmd.arg(id).arg(file1).run();
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
if is_ci() && result.stderr_str().contains("chown: invalid user:") {
// With some Ubuntu into the CI, we can get this answer
let result = scene.ucmd().arg(user_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'
return;
}
assert!(result.success);
result.stderr_contains(&"retained as");
scene
.ucmd()
.arg("0")
.arg("--verbose")
.arg(file1)
.fails()
.stderr_contains(&"failed to change");
}
#[test]
fn test_chown_only_group_id() {
// test chown :1111 file.txt
let result = TestScenario::new("id").ucmd_keepenv().arg("-g").run();
if is_ci() && result.stderr_str().contains("No such user/group") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let result = scene.cmd_keepenv("id").arg("-g").run();
if skipping_test_is_okay(&result, "id: cannot find name for group ID") {
return;
}
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
let id = String::from(result.stdout_str().trim());
let (at, mut ucmd) = at_and_ucmd!();
let file1 = "test_install_target_dir_file_a1";
let group_id = String::from(result.stdout_str().trim());
assert!(!group_id.is_empty());
let file1 = "test_chown_file1";
at.touch(file1);
let perm = ":".to_owned() + &id;
let result = ucmd.arg(perm).arg(file1).run();
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
if is_ci() && result.stderr_str().contains("chown: invalid group:") {
let result = scene
.ucmd()
.arg(format!(":{}", group_id))
.arg("--verbose")
.arg(file1)
.run();
if skipping_test_is_okay(&result, "chown: invalid group:") {
// With mac into the CI, we can get this answer
return;
}
assert!(result.success);
result.stderr_contains(&"retained as");
// Apparently on CI "macos-latest, x86_64-apple-darwin, feat_os_macos"
// the process has the rights to change from runner:staff to runner:wheel
#[cfg(any(windows, all(unix, not(target_os = "macos"))))]
scene
.ucmd()
.arg(":0")
.arg("--verbose")
.arg(file1)
.fails()
.stderr_contains(&"failed to change");
}
#[test]
fn test_chown_both_id() {
fn test_chown_owner_group_id() {
// test chown 1111:1111 file.txt
let result = TestScenario::new("id").ucmd_keepenv().arg("-u").run();
if is_ci() && result.stderr_str().contains("No such user/group") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let result = scene.cmd_keepenv("id").arg("-u").run();
if skipping_test_is_okay(&result, "id: cannot find name for group ID") {
return;
}
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
let id_user = String::from(result.stdout_str().trim());
let user_id = String::from(result.stdout_str().trim());
assert!(!user_id.is_empty());
let result = TestScenario::new("id").ucmd_keepenv().arg("-g").run();
if is_ci() && result.stderr_str().contains("No such user/group") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
let result = scene.cmd_keepenv("id").arg("-g").run();
if skipping_test_is_okay(&result, "id: cannot find name for group ID") {
return;
}
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
let id_group = String::from(result.stdout_str().trim());
let (at, mut ucmd) = at_and_ucmd!();
let file1 = "test_install_target_dir_file_a1";
let group_id = String::from(result.stdout_str().trim());
assert!(!group_id.is_empty());
let file1 = "test_chown_file1";
at.touch(file1);
let perm = id_user + &":".to_owned() + &id_group;
let result = ucmd.arg(perm).arg(file1).run();
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
if is_ci() && result.stderr_str().contains("invalid user") {
// In the CI, some server are failing to return id.
// As seems to be a configuration issue, ignoring it
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");
assert!(result.success);
scene
.ucmd()
.arg("0:0")
.arg("--verbose")
.arg(file1)
.fails()
.stderr_contains(&"failed to change");
}
#[test]
fn test_chown_both_mix() {
// test chown 1111:1111 file.txt
let result = TestScenario::new("id").ucmd_keepenv().arg("-u").run();
if is_ci() && result.stderr_str().contains("No such user/group") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
return;
}
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
let id_user = String::from(result.stdout_str().trim());
fn test_chown_owner_group_mix() {
// test chown 1111:group file.txt
let result = TestScenario::new("id").ucmd_keepenv().arg("-gn").run();
if is_ci() && result.stderr_str().contains("No such user/group") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let result = scene.cmd_keepenv("id").arg("-u").run();
if skipping_test_is_okay(&result, "id: cannot find name for group ID") {
return;
}
let user_id = String::from(result.stdout_str().trim());
assert!(!user_id.is_empty());
let result = scene.cmd_keepenv("id").arg("-gn").run();
if skipping_test_is_okay(&result, "id: cannot find name for group ID") {
return;
}
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
let group_name = String::from(result.stdout_str().trim());
assert!(!group_name.is_empty());
let (at, mut ucmd) = at_and_ucmd!();
let file1 = "test_install_target_dir_file_a1";
let file1 = "test_chown_file1";
at.touch(file1);
let perm = id_user + &":".to_owned() + &group_name;
let result = ucmd.arg(perm).arg(file1).run();
let result = scene
.ucmd()
.arg(format!("{}:{}", user_id, group_name))
.arg("--verbose")
.arg(file1)
.run();
result.stderr_contains(&"retained as");
if is_ci() && result.stderr_str().contains("invalid user") {
// In the CI, some server are failing to return id.
// As seems to be a configuration issue, ignoring it
return;
}
assert!(result.success);
// TODO: on macos group name is not recognized correctly: "chown: invalid group: '0:root'
#[cfg(any(windows, all(unix, not(target_os = "macos"))))]
scene
.ucmd()
.arg("0:root")
.arg("--verbose")
.arg(file1)
.fails()
.stderr_contains(&"failed to change");
}
#[test]
fn test_chown_recursive() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let result = scene.cmd("whoami").run();
if is_ci() && result.stderr_str().contains("No such user/group") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
if skipping_test_is_okay(&result, "whoami: cannot find name for user ID") {
return;
}
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
let username = result.stdout_str().trim_end();
let user_name = String::from(result.stdout_str().trim());
assert!(!user_name.is_empty());
let (at, mut ucmd) = at_and_ucmd!();
at.mkdir("a");
at.mkdir("a/b");
at.mkdir("a/b/c");
at.mkdir_all("a/b/c");
at.mkdir("z");
at.touch(&at.plus_as_string("a/a"));
at.touch(&at.plus_as_string("a/b/b"));
at.touch(&at.plus_as_string("a/b/c/c"));
at.touch(&at.plus_as_string("z/y"));
let result = ucmd
let result = scene
.ucmd()
.arg("-R")
.arg("--verbose")
.arg(username)
.arg(user_name)
.arg("a")
.arg("z")
.run();
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
if is_ci() && result.stderr_str().contains("invalid user") {
// In the CI, some server are failing to return id.
// As seems to be a configuration issue, ignoring it
return;
}
result
.stderr_contains(&"ownership of 'a/a' retained as")
.stderr_contains(&"ownership of 'z/y' retained as")
.success();
result.stderr_contains(&"ownership of 'a/a' retained as");
result.stderr_contains(&"ownership of 'z/y' retained as");
}
#[test]
fn test_root_preserve() {
let scene = TestScenario::new(util_name!());
let result = scene.cmd("whoami").run();
if is_ci() && result.stderr_str().contains("No such user/group") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
if skipping_test_is_okay(&result, "whoami: cannot find name for user ID") {
return;
}
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
let username = result.stdout_str().trim_end();
let user_name = String::from(result.stdout_str().trim());
assert!(!user_name.is_empty());
let result = new_ucmd!()
let result = scene
.ucmd()
.arg("--preserve-root")
.arg("-R")
.arg(username)
.arg(user_name)
.arg("/")
.fails();
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
if is_ci() && result.stderr_str().contains("invalid user") {
// In the CI, some server are failing to return id.
// As seems to be a configuration issue, ignoring it
return;
}
assert!(result
.stderr
.contains("chown: it is dangerous to operate recursively"));
result.stderr_contains(&"chown: it is dangerous to operate recursively");
}
#[cfg(target_os = "linux")]
@ -393,8 +509,34 @@ fn test_big_p() {
.arg("bin")
.arg("/proc/self/cwd")
.fails()
.stderr_is(
"chown: changing ownership of '/proc/self/cwd': Operation not permitted (os error 1)\n",
.stderr_contains(
"chown: changing ownership of '/proc/self/cwd': Operation not permitted (os error 1)",
);
}
}
#[test]
fn test_chown_file_notexisting() {
// test chown username not_existing
let scene = TestScenario::new(util_name!());
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 _result = scene
.ucmd()
.arg(user_name)
.arg("--verbose")
.arg("not_existing")
.fails();
// TODO: uncomment once "failed to change ownership of '{}' to {}" added to stdout
// result.stderr_contains(&"retained as");
// TODO: uncomment once message changed from "cannot dereference" to "cannot access"
// result.stderr_contains(&"cannot access 'not_existing': No such file or directory");
}

View file

@ -31,41 +31,50 @@ fn test_empty() {
at.touch("a");
ucmd.arg("a").succeeds().stdout.ends_with("0 a");
ucmd.arg("a")
.succeeds()
.no_stderr()
.normalized_newlines_stdout_is("4294967295 0 a\n");
}
#[test]
#[ignore]
fn test_arg_overrides_stdin() {
let (at, mut ucmd) = at_and_ucmd!();
let input = "foobarfoobar";
at.touch("a");
let result = ucmd.arg("a").pipe_in(input.as_bytes()).run();
println!("{}, {}", result.stdout, result.stderr);
assert!(result.stdout.ends_with("0 a\n"))
ucmd.arg("a")
.pipe_in(input.as_bytes())
// the command might have exited before all bytes have been pipe in.
// in that case, we don't care about the error (broken pipe)
.ignore_stdin_write_error()
.succeeds()
.no_stderr()
.normalized_newlines_stdout_is("4294967295 0 a\n");
}
#[test]
fn test_invalid_file() {
let (_, mut ucmd) = at_and_ucmd!();
let ts = TestScenario::new(util_name!());
let at = ts.fixtures.clone();
let ls = TestScenario::new("ls");
let files = ls.cmd("ls").arg("-l").run();
println!("{:?}", files.stdout);
println!("{:?}", files.stderr);
let folder_name = "asdf";
let folder_name = "asdf".to_string();
// First check when file doesn't exist
ts.ucmd()
.arg(folder_name)
.fails()
.no_stdout()
.stderr_contains("cksum: error: 'asdf' No such file or directory");
let result = ucmd.arg(&folder_name).run();
println!("stdout: {:?}", result.stdout);
println!("stderr: {:?}", result.stderr);
assert!(result.stderr.contains("cksum: error: 'asdf'"));
assert!(!result.success);
// Then check when the file is of an invalid type
at.mkdir(folder_name);
ts.ucmd()
.arg(folder_name)
.fails()
.no_stdout()
.stderr_contains("cksum: error: 'asdf' Is a directory");
}
// Make sure crc is correct for files larger than 32 bytes
@ -74,14 +83,13 @@ fn test_invalid_file() {
fn test_crc_for_bigger_than_32_bytes() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("chars.txt").run();
let result = ucmd.arg("chars.txt").succeeds();
let mut stdout_splitted = result.stdout.split(" ");
let mut stdout_splitted = result.stdout_str().split(" ");
let cksum: i64 = stdout_splitted.next().unwrap().parse().unwrap();
let bytes_cnt: i64 = stdout_splitted.next().unwrap().parse().unwrap();
assert!(result.success);
assert_eq!(cksum, 586047089);
assert_eq!(bytes_cnt, 16);
}
@ -90,14 +98,13 @@ fn test_crc_for_bigger_than_32_bytes() {
fn test_stdin_larger_than_128_bytes() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("larger_than_2056_bytes.txt").run();
let result = ucmd.arg("larger_than_2056_bytes.txt").succeeds();
let mut stdout_splitted = result.stdout.split(" ");
let mut stdout_splitted = result.stdout_str().split(" ");
let cksum: i64 = stdout_splitted.next().unwrap().parse().unwrap();
let bytes_cnt: i64 = stdout_splitted.next().unwrap().parse().unwrap();
assert!(result.success);
assert_eq!(cksum, 945881979);
assert_eq!(bytes_cnt, 2058);
}

View file

@ -1029,7 +1029,7 @@ fn test_cp_one_file_system() {
at_src.mkdir(TEST_MOUNT_MOUNTPOINT);
let mountpoint_path = &at_src.plus_as_string(TEST_MOUNT_MOUNTPOINT);
let _r = scene
scene
.cmd("mount")
.arg("-t")
.arg("tmpfs")
@ -1037,8 +1037,7 @@ fn test_cp_one_file_system() {
.arg("size=640k") // ought to be enough
.arg("tmpfs")
.arg(mountpoint_path)
.run();
assert!(_r.code == Some(0), "{}", _r.stderr);
.succeeds();
at_src.touch(TEST_MOUNT_OTHER_FILESYSTEM_FILE);
@ -1051,8 +1050,7 @@ fn test_cp_one_file_system() {
.run();
// Ditch the mount before the asserts
let _r = scene.cmd("umount").arg(mountpoint_path).run();
assert!(_r.code == Some(0), "{}", _r.stderr);
scene.cmd("umount").arg(mountpoint_path).succeeds();
assert!(result.success);
assert!(!at_dst.file_exists(TEST_MOUNT_OTHER_FILESYSTEM_FILE));

View file

@ -7,12 +7,10 @@ const SUB_LINK: &str = "subdir/links/sublink.txt";
#[test]
fn test_du_basics() {
new_ucmd!()
.succeeds()
.no_stderr();
new_ucmd!().succeeds().no_stderr();
}
#[cfg(target_vendor = "apple")]
fn _du_basics(s: String) {
fn _du_basics(s: &str) {
let answer = "32\t./subdir
8\t./subdir/deeper
24\t./subdir/links
@ -32,11 +30,18 @@ fn _du_basics(s: &str) {
#[test]
fn test_du_basics_subdir() {
let (_at, mut ucmd) = at_and_ucmd!();
let scene = TestScenario::new(util_name!());
let result = ucmd.arg(SUB_DIR).run();
assert!(result.success);
assert_eq!(result.stderr, "");
let result = scene.ucmd().arg(SUB_DIR).succeeds();
#[cfg(target_os = "linux")]
{
let result_reference = scene.cmd("du").arg(SUB_DIR).run();
if result_reference.succeeded() {
assert_eq!(result.stdout_str(), result_reference.stdout_str());
return;
}
}
_du_basics_subdir(result.stdout_str());
}
@ -60,26 +65,29 @@ fn _du_basics_subdir(s: &str) {
#[test]
fn test_du_basics_bad_name() {
let (_at, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("bad_name").run();
assert_eq!(result.stdout_str(), "");
assert_eq!(
result.stderr,
"du: error: bad_name: No such file or directory\n"
);
new_ucmd!()
.arg("bad_name")
.succeeds() // TODO: replace with ".fails()" once `du` is fixed
.stderr_only("du: error: bad_name: No such file or directory\n");
}
#[test]
fn test_du_soft_link() {
let ts = TestScenario::new("du");
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let link = ts.ccmd("ln").arg("-s").arg(SUB_FILE).arg(SUB_LINK).run();
assert!(link.success);
at.symlink_file(SUB_FILE, SUB_LINK);
let result = ts.ucmd().arg(SUB_DIR_LINKS).run();
assert!(result.success);
assert_eq!(result.stderr, "");
let result = scene.ucmd().arg(SUB_DIR_LINKS).succeeds();
#[cfg(target_os = "linux")]
{
let result_reference = scene.cmd("du").arg(SUB_DIR_LINKS).run();
if result_reference.succeeded() {
assert_eq!(result.stdout_str(), result_reference.stdout_str());
return;
}
}
_du_soft_link(result.stdout_str());
}
@ -104,14 +112,23 @@ fn _du_soft_link(s: &str) {
#[test]
fn test_du_hard_link() {
let ts = TestScenario::new("du");
let scene = TestScenario::new(util_name!());
let link = ts.ccmd("ln").arg(SUB_FILE).arg(SUB_LINK).run();
assert!(link.success);
let result_ln = scene.cmd("ln").arg(SUB_FILE).arg(SUB_LINK).run();
if !result_ln.succeeded() {
scene.ccmd("ln").arg(SUB_FILE).arg(SUB_LINK).succeeds();
}
let result = ts.ucmd().arg(SUB_DIR_LINKS).run();
assert!(result.success);
assert_eq!(result.stderr, "");
let result = scene.ucmd().arg(SUB_DIR_LINKS).succeeds();
#[cfg(target_os = "linux")]
{
let result_reference = scene.cmd("du").arg(SUB_DIR_LINKS).run();
if result_reference.succeeded() {
assert_eq!(result.stdout_str(), result_reference.stdout_str());
return;
}
}
// We do not double count hard links as the inodes are identical
_du_hard_link(result.stdout_str());
}
@ -136,11 +153,23 @@ fn _du_hard_link(s: &str) {
#[test]
fn test_du_d_flag() {
let ts = TestScenario::new("du");
let scene = TestScenario::new(util_name!());
let result = ts.ucmd().arg("-d").arg("1").run();
assert!(result.success);
assert_eq!(result.stderr, "");
let result = scene.ucmd().arg("-d1").succeeds();
#[cfg(target_os = "linux")]
{
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")
);
return;
}
}
_du_d_flag(result.stdout_str());
}
@ -164,9 +193,7 @@ fn _du_d_flag(s: &str) {
#[test]
fn test_du_h_flag_empty_file() {
let ts = TestScenario::new("du");
ts.ucmd()
new_ucmd!()
.arg("-h")
.arg("empty.txt")
.succeeds()
@ -176,17 +203,51 @@ fn test_du_h_flag_empty_file() {
#[cfg(feature = "touch")]
#[test]
fn test_du_time() {
let ts = TestScenario::new("du");
let scene = TestScenario::new(util_name!());
let touch = ts.ccmd("touch").arg("-a").arg("-m").arg("-t").arg("201505150000").arg("date_test").run();
assert!(touch.success);
scene
.ccmd("touch")
.arg("-a")
.arg("-m")
.arg("-t")
.arg("201505150000")
.arg("date_test")
.succeeds();
let result = ts.ucmd().arg("--time").arg("date_test").run();
scene
.ucmd()
.arg("--time")
.arg("date_test")
.succeeds()
.stdout_only("0\t2015-05-15 00:00\tdate_test\n");
// cleanup by removing test file
ts.cmd("rm").arg("date_test").run();
assert!(result.success);
assert_eq!(result.stderr, "");
assert_eq!(result.stdout, "0\t2015-05-15 00:00\tdate_test\n");
scene.cmd("rm").arg("date_test").succeeds(); // TODO: is this necessary?
}
#[cfg(not(target_os = "windows"))]
#[cfg(feature = "chmod")]
#[test]
fn test_du_no_permission() {
let ts = TestScenario::new(util_name!());
let _chmod = ts.ccmd("chmod").arg("-r").arg(SUB_DIR_LINKS).succeeds();
let result = ts.ucmd().arg(SUB_DIR_LINKS).succeeds();
ts.ccmd("chmod").arg("+r").arg(SUB_DIR_LINKS).run();
assert_eq!(
result.stderr_str(),
"du: cannot read directory subdir/links: Permission denied (os error 13)\n"
);
_du_no_permission(result.stdout_str());
}
#[cfg(target_vendor = "apple")]
fn _du_no_permission(s: &str) {
assert_eq!(s, "0\tsubdir/links\n");
}
#[cfg(all(not(target_vendor = "apple"), not(target_os = "windows")))]
fn _du_no_permission(s: &str) {
assert_eq!(s, "4\tsubdir/links\n");
}

View file

@ -2,10 +2,7 @@ use crate::common::util::*;
#[test]
fn test_default() {
new_ucmd!()
.arg("hi")
.succeeds()
.stdout_only("hi\n");
new_ucmd!().arg("hi").succeeds().stdout_only("hi\n");
}
#[test]

View file

@ -26,17 +26,18 @@ fn test_env_version() {
#[test]
fn test_echo() {
let result = new_ucmd!()
.arg("echo")
.arg("FOO-bar")
.succeeds();
let result = new_ucmd!().arg("echo").arg("FOO-bar").succeeds();
assert_eq!(result.stdout_str().trim(), "FOO-bar");
}
#[test]
fn test_file_option() {
let out = new_ucmd!().arg("-f").arg("vars.conf.txt").run().stdout_move_str();
let out = new_ucmd!()
.arg("-f")
.arg("vars.conf.txt")
.run()
.stdout_move_str();
assert_eq!(
out.lines()
@ -89,7 +90,8 @@ fn test_multiple_name_value_pairs() {
let out = new_ucmd!().arg("FOO=bar").arg("ABC=xyz").run();
assert_eq!(
out.stdout_str().lines()
out.stdout_str()
.lines()
.filter(|&line| line == "FOO=bar" || line == "ABC=xyz")
.count(),
2

View file

@ -542,4 +542,4 @@ fn test_obsolete_syntax() {
.arg("space_separated_words.txt")
.succeeds()
.stdout_is("test1\n \ntest2\n \ntest3\n \ntest4\n \ntest5\n \ntest6\n ");
}
}

View file

@ -4,10 +4,6 @@ use self::regex::Regex;
#[test]
fn test_normal() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.run();
assert!(result.success);
let re = Regex::new(r"^[0-9a-f]{8}").unwrap();
assert!(re.is_match(&result.stdout_str()));
new_ucmd!().succeeds().stdout_matches(&re);
}

View file

@ -14,9 +14,7 @@ fn test_hostname() {
#[cfg(not(target_vendor = "apple"))]
#[test]
fn test_hostname_ip() {
let result = new_ucmd!().arg("-i").run();
println!("{:#?}", result);
assert!(result.success);
let result = new_ucmd!().arg("-i").succeeds();
assert!(!result.stdout_str().trim().is_empty());
}
@ -25,6 +23,8 @@ fn test_hostname_full() {
let ls_short_res = new_ucmd!().arg("-s").succeeds();
assert!(!ls_short_res.stdout_str().trim().is_empty());
new_ucmd!().arg("-f").succeeds()
new_ucmd!()
.arg("-f")
.succeeds()
.stdout_contains(ls_short_res.stdout_str().trim());
}

View file

@ -1,11 +1,32 @@
use crate::common::util::*;
// Apparently some CI environments have configuration issues, e.g. with 'whoami' and 'id'.
// If we are running inside the CI and "needle" is in "stderr" skipping this test is
// considered okay. If we are not inside the CI this calls assert!(result.success).
//
// From the Logs: "Build (ubuntu-18.04, x86_64-unknown-linux-gnu, feat_os_unix, use-cross)"
// stderr: "whoami: cannot find name for user ID 1001"
// Maybe: "adduser --uid 1001 username" can put things right?
// stderr = id: error: Could not find uid 1001: No such id: 1001
fn skipping_test_is_okay(result: &CmdResult, needle: &str) -> bool {
if !result.succeeded() {
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
if is_ci() && result.stderr_str().contains(needle) {
println!("test skipped:");
return true;
} else {
result.success();
}
}
false
}
fn return_whoami_username() -> String {
let scene = TestScenario::new("whoami");
let result = scene.cmd("whoami").run();
if is_ci() && result.stderr.contains("cannot find name for user ID") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
if skipping_test_is_okay(&result, "whoami: cannot find name for user ID") {
println!("test skipped:");
return String::from("");
}
@ -14,39 +35,41 @@ fn return_whoami_username() -> String {
#[test]
fn test_id() {
let result = new_ucmd!().arg("-u").run();
if result.stderr.contains("cannot find name for user ID") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
let scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg("-u").succeeds();
let uid = result.stdout_str().trim();
let result = scene.ucmd().run();
if skipping_test_is_okay(&result, "Could not find uid") {
return;
}
let uid = result.success().stdout_str().trim();
let result = new_ucmd!().run();
if is_ci() && result.stderr.contains("cannot find name for user ID") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
return;
}
if !result.stderr_str().contains("Could not find uid") {
// Verify that the id found by --user/-u exists in the list
result.success().stdout_contains(&uid);
}
// Verify that the id found by --user/-u exists in the list
result.stdout_contains(uid);
}
#[test]
fn test_id_from_name() {
let username = return_whoami_username();
if username == "" {
// Sometimes, the CI is failing here
if username.is_empty() {
return;
}
let scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg(&username).run();
if skipping_test_is_okay(&result, "Could not find uid") {
return;
}
let result = new_ucmd!().arg(&username).succeeds();
let uid = result.stdout_str().trim();
new_ucmd!().succeeds()
let result = scene.ucmd().run();
if skipping_test_is_okay(&result, "Could not find uid") {
return;
}
result
// Verify that the id found by --user/-u exists in the list
.stdout_contains(uid)
// Verify that the username found by whoami exists in the list
@ -55,51 +78,42 @@ fn test_id_from_name() {
#[test]
fn test_id_name_from_id() {
let result = new_ucmd!().arg("-u").succeeds();
let uid = result.stdout_str().trim();
let result = new_ucmd!().arg("-nu").run();
let result = new_ucmd!().arg("-nu").arg(uid).run();
if is_ci() && result.stderr.contains("No such user/group") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
let username_id = result.stdout_str().trim();
let username_whoami = return_whoami_username();
if username_whoami.is_empty() {
return;
}
let username_id = result
.success()
.stdout_str()
.trim();
let scene = TestScenario::new("whoami");
let result = scene.cmd("whoami").succeeds();
let username_whoami = result.stdout_str().trim();
assert_eq!(username_id, username_whoami);
}
#[test]
fn test_id_group() {
let mut result = new_ucmd!().arg("-g").succeeds();
let scene = TestScenario::new(util_name!());
let mut result = scene.ucmd().arg("-g").succeeds();
let s1 = result.stdout_str().trim();
assert!(s1.parse::<f64>().is_ok());
result = new_ucmd!().arg("--group").succeeds();
result = scene.ucmd().arg("--group").succeeds();
let s1 = result.stdout_str().trim();
assert!(s1.parse::<f64>().is_ok());
}
#[test]
fn test_id_groups() {
let result = new_ucmd!().arg("-G").succeeds();
assert!(result.success);
let scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg("-G").succeeds();
let groups = result.stdout_str().trim().split_whitespace();
for s in groups {
assert!(s.parse::<f64>().is_ok());
}
let result = new_ucmd!().arg("--groups").succeeds();
assert!(result.success);
let result = scene.ucmd().arg("--groups").succeeds();
let groups = result.stdout_str().trim().split_whitespace();
for s in groups {
assert!(s.parse::<f64>().is_ok());
@ -108,11 +122,13 @@ fn test_id_groups() {
#[test]
fn test_id_user() {
let mut result = new_ucmd!().arg("-u").succeeds();
let scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg("-u").succeeds();
let s1 = result.stdout_str().trim();
assert!(s1.parse::<f64>().is_ok());
result = new_ucmd!().arg("--user").succeeds();
let result = scene.ucmd().arg("--user").succeeds();
let s1 = result.stdout_str().trim();
assert!(s1.parse::<f64>().is_ok());
}
@ -120,28 +136,34 @@ fn test_id_user() {
#[test]
fn test_id_pretty_print() {
let username = return_whoami_username();
if username == "" {
// Sometimes, the CI is failing here
if username.is_empty() {
return;
}
let result = new_ucmd!().arg("-p").run();
if result.stdout_str().trim() == "" {
// Sometimes, the CI is failing here with
// old rust versions on Linux
let scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg("-p").run();
if result.stdout_str().trim().is_empty() {
// this fails only on: "MinRustV (ubuntu-latest, feat_os_unix)"
// `rustc 1.40.0 (73528e339 2019-12-16)`
// run: /home/runner/work/coreutils/coreutils/target/debug/coreutils id -p
// thread 'test_id::test_id_pretty_print' panicked at 'Command was expected to succeed.
// stdout =
// stderr = ', tests/common/util.rs:157:13
println!("test skipped:");
return;
}
result.success().stdout_contains(username);
}
#[test]
fn test_id_password_style() {
let username = return_whoami_username();
if username == "" {
// Sometimes, the CI is failing here
if username.is_empty() {
return;
}
let result = new_ucmd!().arg("-P").succeeds();
assert!(result.stdout_str().starts_with(&username));
}

View file

@ -359,7 +359,7 @@ fn test_install_target_new_file_failing_nonexistent_parent() {
ucmd.arg(file1)
.arg(format!("{}/{}", dir, file2))
.fails()
.stderr_contains(&"not a directory");
.stderr_contains(&"No such file or directory");
}
#[test]
@ -443,9 +443,12 @@ fn test_install_failing_omitting_directory() {
at.mkdir(dir2);
at.touch(file1);
let r = ucmd.arg(dir1).arg(file1).arg(dir2).run();
assert!(r.code == Some(1));
assert!(r.stderr.contains("omitting directory"));
ucmd.arg(dir1)
.arg(file1)
.arg(dir2)
.fails()
.code_is(1)
.stderr_contains("omitting directory");
}
#[test]
@ -458,9 +461,12 @@ fn test_install_failing_no_such_file() {
at.mkdir(dir1);
at.touch(file1);
let r = ucmd.arg(file1).arg(file2).arg(dir1).run();
assert!(r.code == Some(1));
assert!(r.stderr.contains("No such file or directory"));
ucmd.arg(file1)
.arg(file2)
.arg(dir1)
.fails()
.code_is(1)
.stderr_contains("No such file or directory");
}
#[test]
@ -643,3 +649,42 @@ fn test_install_and_strip_with_non_existent_program() {
.stderr;
assert!(stderr.contains("No such file or directory"));
}
#[test]
fn test_install_creating_leading_dirs() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let source = "create_leading_test_file";
let target = "dir1/dir2/dir3/test_file";
at.touch(source);
scene
.ucmd()
.arg("-D")
.arg(source)
.arg(at.plus(target))
.succeeds()
.no_stderr();
}
#[test]
#[cfg(not(windows))]
fn test_install_creating_leading_dir_fails_on_long_name() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let source = "create_leading_test_file";
let target = format!("{}/test_file", "d".repeat(libc::PATH_MAX as usize + 1));
at.touch(source);
scene
.ucmd()
.arg("-D")
.arg(source)
.arg(at.plus(target.as_str()))
.fails()
.stderr_contains("failed to create");
}

View file

@ -5,6 +5,7 @@ use crate::common::util::*;
extern crate regex;
use self::regex::Regex;
use std::path::Path;
use std::thread::sleep;
use std::time::Duration;
@ -1456,3 +1457,219 @@ fn test_ls_ignore_backups() {
.stdout_does_not_contain("somebackup")
.stdout_does_not_contain(".somehiddenbackup~");
}
#[test]
fn test_ls_directory() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.mkdir("some_dir");
at.symlink_dir("some_dir", "sym_dir");
at.touch(Path::new("some_dir").join("nested_file").to_str().unwrap());
scene
.ucmd()
.arg("some_dir")
.succeeds()
.stdout_is("nested_file\n");
scene
.ucmd()
.arg("--directory")
.arg("some_dir")
.succeeds()
.stdout_is("some_dir\n");
scene
.ucmd()
.arg("sym_dir")
.succeeds()
.stdout_is("nested_file\n");
}
#[test]
fn test_ls_deref_command_line() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.touch("some_file");
at.symlink_file("some_file", "sym_file");
scene
.ucmd()
.arg("sym_file")
.succeeds()
.stdout_is("sym_file\n");
// -l changes the default to no dereferencing
scene
.ucmd()
.arg("-l")
.arg("sym_file")
.succeeds()
.stdout_contains("sym_file ->");
scene
.ucmd()
.arg("--dereference-command-line-symlink-to-dir")
.arg("sym_file")
.succeeds()
.stdout_is("sym_file\n");
scene
.ucmd()
.arg("-l")
.arg("--dereference-command-line-symlink-to-dir")
.arg("sym_file")
.succeeds()
.stdout_contains("sym_file ->");
scene
.ucmd()
.arg("--dereference-command-line")
.arg("sym_file")
.succeeds()
.stdout_is("sym_file\n");
let result = scene
.ucmd()
.arg("-l")
.arg("--dereference-command-line")
.arg("sym_file")
.succeeds();
assert!(!result.stdout_str().contains("->"));
let result = scene.ucmd().arg("-lH").arg("sym_file").succeeds();
assert!(!result.stdout_str().contains("sym_file ->"));
// If the symlink is not a command line argument, it must be shown normally
scene
.ucmd()
.arg("-l")
.arg("--dereference-command-line")
.succeeds()
.stdout_contains("sym_file ->");
}
#[test]
fn test_ls_deref_command_line_dir() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.mkdir("some_dir");
at.symlink_dir("some_dir", "sym_dir");
at.touch(Path::new("some_dir").join("nested_file").to_str().unwrap());
scene
.ucmd()
.arg("sym_dir")
.succeeds()
.stdout_contains("nested_file");
scene
.ucmd()
.arg("-l")
.arg("sym_dir")
.succeeds()
.stdout_contains("sym_dir ->");
scene
.ucmd()
.arg("--dereference-command-line-symlink-to-dir")
.arg("sym_dir")
.succeeds()
.stdout_contains("nested_file");
scene
.ucmd()
.arg("-l")
.arg("--dereference-command-line-symlink-to-dir")
.arg("sym_dir")
.succeeds()
.stdout_contains("nested_file");
scene
.ucmd()
.arg("--dereference-command-line")
.arg("sym_dir")
.succeeds()
.stdout_contains("nested_file");
scene
.ucmd()
.arg("-l")
.arg("--dereference-command-line")
.arg("sym_dir")
.succeeds()
.stdout_contains("nested_file");
scene
.ucmd()
.arg("-lH")
.arg("sym_dir")
.succeeds()
.stdout_contains("nested_file");
// If the symlink is not a command line argument, it must be shown normally
scene
.ucmd()
.arg("-l")
.arg("--dereference-command-line")
.succeeds()
.stdout_contains("sym_dir ->");
scene
.ucmd()
.arg("-lH")
.succeeds()
.stdout_contains("sym_dir ->");
scene
.ucmd()
.arg("-l")
.arg("--dereference-command-line-symlink-to-dir")
.succeeds()
.stdout_contains("sym_dir ->");
// --directory does not dereference anything by default
scene
.ucmd()
.arg("-l")
.arg("--directory")
.arg("sym_dir")
.succeeds()
.stdout_contains("sym_dir ->");
let result = scene
.ucmd()
.arg("-l")
.arg("--directory")
.arg("--dereference-command-line-symlink-to-dir")
.arg("sym_dir")
.succeeds();
assert!(!result.stdout_str().ends_with("sym_dir"));
// --classify does not dereference anything by default
scene
.ucmd()
.arg("-l")
.arg("--directory")
.arg("sym_dir")
.succeeds()
.stdout_contains("sym_dir ->");
let result = scene
.ucmd()
.arg("-l")
.arg("--directory")
.arg("--dereference-command-line-symlink-to-dir")
.arg("sym_dir")
.succeeds();
assert!(!result.stdout_str().ends_with("sym_dir"));
}

View file

@ -113,17 +113,14 @@ fn test_mktemp_mktemp_t() {
.arg("-t")
.arg(TEST_TEMPLATE7)
.succeeds();
let result = scene
scene
.ucmd()
.env(TMPDIR, &pathname)
.arg("-t")
.arg(TEST_TEMPLATE8)
.fails();
println!("stdout {}", result.stdout);
println!("stderr {}", result.stderr);
assert!(result
.stderr
.contains("error: suffix cannot contain any path separators"));
.fails()
.no_stdout()
.stderr_contains("error: suffix cannot contain any path separators");
}
#[test]
@ -391,10 +388,8 @@ fn test_mktemp_tmpdir_one_arg() {
.arg("--tmpdir")
.arg("apt-key-gpghome.XXXXXXXXXX")
.succeeds();
println!("stdout {}", result.stdout);
println!("stderr {}", result.stderr);
assert!(result.stdout.contains("apt-key-gpghome."));
assert!(PathBuf::from(result.stdout.trim()).is_file());
result.no_stderr().stdout_contains("apt-key-gpghome.");
assert!(PathBuf::from(result.stdout_str().trim()).is_file());
}
#[test]
@ -407,8 +402,6 @@ fn test_mktemp_directory_tmpdir() {
.arg("--tmpdir")
.arg("apt-key-gpghome.XXXXXXXXXX")
.succeeds();
println!("stdout {}", result.stdout);
println!("stderr {}", result.stderr);
assert!(result.stdout.contains("apt-key-gpghome."));
assert!(PathBuf::from(result.stdout.trim()).is_dir());
result.no_stderr().stdout_contains("apt-key-gpghome.");
assert!(PathBuf::from(result.stdout_str().trim()).is_dir());
}

View file

@ -2,54 +2,46 @@ use crate::common::util::*;
#[test]
fn test_nproc() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.run();
assert!(result.success);
let nproc: u8 = result.stdout.trim().parse().unwrap();
let nproc: u8 = new_ucmd!().succeeds().stdout_str().trim().parse().unwrap();
assert!(nproc > 0);
}
#[test]
fn test_nproc_all_omp() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("--all").run();
assert!(result.success);
let nproc: u8 = result.stdout.trim().parse().unwrap();
let result = new_ucmd!().arg("--all").succeeds();
let nproc: u8 = result.stdout_str().trim().parse().unwrap();
assert!(nproc > 0);
let result = TestScenario::new(util_name!())
.ucmd_keepenv()
.env("OMP_NUM_THREADS", "1")
.run();
assert!(result.success);
let nproc_omp: u8 = result.stdout.trim().parse().unwrap();
.succeeds();
let nproc_omp: u8 = result.stdout_str().trim().parse().unwrap();
assert!(nproc - 1 == nproc_omp);
let result = TestScenario::new(util_name!())
.ucmd_keepenv()
.env("OMP_NUM_THREADS", "1") // Has no effect
.arg("--all")
.run();
assert!(result.success);
let nproc_omp: u8 = result.stdout.trim().parse().unwrap();
.succeeds();
let nproc_omp: u8 = result.stdout_str().trim().parse().unwrap();
assert!(nproc == nproc_omp);
}
#[test]
fn test_nproc_ignore() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.run();
assert!(result.success);
let nproc: u8 = result.stdout.trim().parse().unwrap();
let result = new_ucmd!().succeeds();
let nproc: u8 = result.stdout_str().trim().parse().unwrap();
if nproc > 1 {
// Ignore all CPU but one
let result = TestScenario::new(util_name!())
.ucmd_keepenv()
.arg("--ignore")
.arg((nproc - 1).to_string())
.run();
assert!(result.success);
let nproc: u8 = result.stdout.trim().parse().unwrap();
.succeeds();
let nproc: u8 = result.stdout_str().trim().parse().unwrap();
assert!(nproc == 1);
}
}

View file

@ -43,11 +43,9 @@ fn test_short_format_i() {
let actual = TestScenario::new(util_name!())
.ucmd()
.args(&args)
.run()
.stdout;
.succeeds()
.stdout_move_str();
let expect = expected_result(&args);
println!("actual: {:?}", actual);
println!("expect: {:?}", expect);
let v_actual: Vec<&str> = actual.split_whitespace().collect();
let v_expect: Vec<&str> = expect.split_whitespace().collect();
assert_eq!(v_actual, v_expect);
@ -62,11 +60,9 @@ fn test_short_format_q() {
let actual = TestScenario::new(util_name!())
.ucmd()
.args(&args)
.run()
.stdout;
.succeeds()
.stdout_move_str();
let expect = expected_result(&args);
println!("actual: {:?}", actual);
println!("expect: {:?}", expect);
let v_actual: Vec<&str> = actual.split_whitespace().collect();
let v_expect: Vec<&str> = expect.split_whitespace().collect();
assert_eq!(v_actual, v_expect);
@ -79,5 +75,5 @@ fn expected_result(args: &[&str]) -> String {
.env("LANGUAGE", "C")
.args(args)
.run()
.stdout
.stdout_move_str()
}

View file

@ -7,10 +7,11 @@ fn test_get_all() {
env::set_var(key, "VALUE");
assert_eq!(env::var(key), Ok("VALUE".to_string()));
let result = TestScenario::new(util_name!()).ucmd_keepenv().run();
assert!(result.success);
assert!(result.stdout.contains("HOME="));
assert!(result.stdout.contains("KEY=VALUE"));
TestScenario::new(util_name!())
.ucmd_keepenv()
.succeeds()
.stdout_contains("HOME=")
.stdout_contains("KEY=VALUE");
}
#[test]
@ -22,9 +23,8 @@ fn test_get_var() {
let result = TestScenario::new(util_name!())
.ucmd_keepenv()
.arg("KEY")
.run();
.succeeds();
assert!(result.success);
assert!(!result.stdout.is_empty());
assert!(result.stdout.trim() == "VALUE");
assert!(!result.stdout_str().is_empty());
assert!(result.stdout_str().trim() == "VALUE");
}

View file

@ -5,7 +5,7 @@ static GIBBERISH: &'static str = "supercalifragilisticexpialidocious";
#[test]
fn test_canonicalize() {
let (at, mut ucmd) = at_and_ucmd!();
let actual = ucmd.arg("-f").arg(".").run().stdout;
let actual = ucmd.arg("-f").arg(".").run().stdout_move_str();
let expect = at.root_dir_resolved() + "\n";
println!("actual: {:?}", actual);
println!("expect: {:?}", expect);
@ -15,7 +15,7 @@ fn test_canonicalize() {
#[test]
fn test_canonicalize_existing() {
let (at, mut ucmd) = at_and_ucmd!();
let actual = ucmd.arg("-e").arg(".").run().stdout;
let actual = ucmd.arg("-e").arg(".").run().stdout_move_str();
let expect = at.root_dir_resolved() + "\n";
println!("actual: {:?}", actual);
println!("expect: {:?}", expect);
@ -25,7 +25,7 @@ fn test_canonicalize_existing() {
#[test]
fn test_canonicalize_missing() {
let (at, mut ucmd) = at_and_ucmd!();
let actual = ucmd.arg("-m").arg(GIBBERISH).run().stdout;
let actual = ucmd.arg("-m").arg(GIBBERISH).run().stdout_move_str();
let expect = path_concat!(at.root_dir_resolved(), GIBBERISH) + "\n";
println!("actual: {:?}", actual);
println!("expect: {:?}", expect);
@ -37,7 +37,7 @@ fn test_long_redirection_to_current_dir() {
let (at, mut ucmd) = at_and_ucmd!();
// Create a 256-character path to current directory
let dir = path_concat!(".", ..128);
let actual = ucmd.arg("-n").arg("-m").arg(dir).run().stdout;
let actual = ucmd.arg("-n").arg("-m").arg(dir).run().stdout_move_str();
let expect = at.root_dir_resolved();
println!("actual: {:?}", actual);
println!("expect: {:?}", expect);
@ -48,7 +48,12 @@ fn test_long_redirection_to_current_dir() {
fn test_long_redirection_to_root() {
// Create a 255-character path to root
let dir = path_concat!("..", ..85);
let actual = new_ucmd!().arg("-n").arg("-m").arg(dir).run().stdout;
let actual = new_ucmd!()
.arg("-n")
.arg("-m")
.arg(dir)
.run()
.stdout_move_str();
let expect = get_root_path();
println!("actual: {:?}", actual);
println!("expect: {:?}", expect);

View file

@ -36,9 +36,7 @@ fn test_shred_force() {
at.set_readonly(file);
// Try shred -u.
let result = scene.ucmd().arg("-u").arg(file).run();
println!("stderr = {:?}", result.stderr);
println!("stdout = {:?}", result.stdout);
scene.ucmd().arg("-u").arg(file).run();
// file_a was not deleted because it is readonly.
assert!(at.file_exists(file));

View file

@ -8,6 +8,25 @@ fn test_helper(file_name: &str, args: &str) {
.stdout_is_fixture(format!("{}.expected", file_name));
}
#[test]
fn test_months_whitespace() {
test_helper("months-whitespace", "-M");
}
#[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]
fn test_human_numeric_whitespace() {
test_helper("human-numeric-whitespace", "-h");
}
#[test]
fn test_multiple_decimals_general() {
new_ucmd!()
@ -19,11 +38,7 @@ fn test_multiple_decimals_general() {
#[test]
fn test_multiple_decimals_numeric() {
new_ucmd!()
.arg("-n")
.arg("multiple_decimals_numeric.txt")
.succeeds()
.stdout_is("-2028789030\n-896689\n-8.90880\n-1\n-.05\n\n\n\n\n\n\n\n\n000\nCARAvan\n00000001\n1\n1.040000000\n1.444\n1.58590\n8.013\n45\n46.89\n 4567.\n4567.1\n4567.34\n\t\t\t\t\t\t\t\t\t\t4567..457\n\t\t\t\t37800\n\t\t\t\t\t\t45670.89079.098\n\t\t\t\t\t\t45670.89079.1\n576,446.88800000\n576,446.890\n4798908.340000000000\n4798908.45\n4798908.8909800\n");
test_helper("multiple_decimals_numeric", "-n")
}
#[test]
@ -50,7 +65,7 @@ fn test_random_shuffle_len() {
// check whether output is the same length as the input
const FILE: &'static str = "default_unsorted_ints.expected";
let (at, _ucmd) = at_and_ucmd!();
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout;
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout_move_str();
let expected = at.read(FILE);
assert_ne!(result, expected);
@ -62,9 +77,9 @@ fn test_random_shuffle_contains_all_lines() {
// check whether lines of input are all in output
const FILE: &'static str = "default_unsorted_ints.expected";
let (at, _ucmd) = at_and_ucmd!();
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout;
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout_move_str();
let expected = at.read(FILE);
let result_sorted = new_ucmd!().pipe_in(result.clone()).run().stdout;
let result_sorted = new_ucmd!().pipe_in(result.clone()).run().stdout_move_str();
assert_ne!(result, expected);
assert_eq!(result_sorted, expected);
@ -77,9 +92,9 @@ fn test_random_shuffle_two_runs_not_the_same() {
// as the starting order, or if both random sorts end up having the same order.
const FILE: &'static str = "default_unsorted_ints.expected";
let (at, _ucmd) = at_and_ucmd!();
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout;
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout_move_str();
let expected = at.read(FILE);
let unexpected = new_ucmd!().arg("-R").arg(FILE).run().stdout;
let unexpected = new_ucmd!().arg("-R").arg(FILE).run().stdout_move_str();
assert_ne!(result, expected);
assert_ne!(result, unexpected);
@ -92,9 +107,9 @@ fn test_random_shuffle_contains_two_runs_not_the_same() {
// as the starting order, or if both random sorts end up having the same order.
const FILE: &'static str = "default_unsorted_ints.expected";
let (at, _ucmd) = at_and_ucmd!();
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout;
let result = new_ucmd!().arg("-R").arg(FILE).run().stdout_move_str();
let expected = at.read(FILE);
let unexpected = new_ucmd!().arg("-R").arg(FILE).run().stdout;
let unexpected = new_ucmd!().arg("-R").arg(FILE).run().stdout_move_str();
assert_ne!(result, expected);
assert_ne!(result, unexpected);

View file

@ -194,7 +194,7 @@ fn test_terse_normal_format() {
// note: contains birth/creation date which increases test fragility
// * results may vary due to built-in `stat` limitations as well as linux kernel and rust version capability variations
let args = ["-t", "/"];
let actual = new_ucmd!().args(&args).run().stdout;
let actual = new_ucmd!().args(&args).succeeds().stdout_move_str();
let expect = expected_result(&args);
println!("actual: {:?}", actual);
println!("expect: {:?}", expect);
@ -216,7 +216,7 @@ fn test_terse_normal_format() {
#[cfg(target_os = "linux")]
fn test_format_created_time() {
let args = ["-c", "%w", "/boot"];
let actual = new_ucmd!().args(&args).run().stdout;
let actual = new_ucmd!().args(&args).succeeds().stdout_move_str();
let expect = expected_result(&args);
println!("actual: {:?}", actual);
println!("expect: {:?}", expect);
@ -240,7 +240,7 @@ fn test_format_created_time() {
#[cfg(target_os = "linux")]
fn test_format_created_seconds() {
let args = ["-c", "%W", "/boot"];
let actual = new_ucmd!().args(&args).run().stdout;
let actual = new_ucmd!().args(&args).succeeds().stdout_move_str();
let expect = expected_result(&args);
println!("actual: {:?}", actual);
println!("expect: {:?}", expect);

View file

@ -25,19 +25,15 @@ fn test_stdbuf_line_buffered_stdout() {
#[cfg(not(target_os = "windows"))]
#[test]
fn test_stdbuf_no_buffer_option_fails() {
new_ucmd!()
.args(&["head"])
.pipe_in("The quick brown fox jumps over the lazy dog.")
.fails()
.stderr_is(
"error: The following required arguments were not provided:\n \
new_ucmd!().args(&["head"]).fails().stderr_is(
"error: The following required arguments were not provided:\n \
--error <MODE>\n \
--input <MODE>\n \
--output <MODE>\n\n\
USAGE:\n \
stdbuf OPTION... COMMAND\n\n\
For more information try --help",
);
);
}
#[cfg(not(target_os = "windows"))]
@ -55,7 +51,6 @@ fn test_stdbuf_trailing_var_arg() {
fn test_stdbuf_line_buffering_stdin_fails() {
new_ucmd!()
.args(&["-i", "L", "head"])
.pipe_in("The quick brown fox jumps over the lazy dog.")
.fails()
.stderr_is("stdbuf: error: line buffering stdin is meaningless\nTry 'stdbuf --help' for more information.");
}
@ -65,7 +60,6 @@ fn test_stdbuf_line_buffering_stdin_fails() {
fn test_stdbuf_invalid_mode_fails() {
new_ucmd!()
.args(&["-i", "1024R", "head"])
.pipe_in("The quick brown fox jumps over the lazy dog.")
.fails()
.stderr_is("stdbuf: error: invalid mode 1024R\nTry 'stdbuf --help' for more information.");
}

View file

@ -5,8 +5,7 @@ use tempfile::tempdir;
#[test]
fn test_sync_default() {
let result = new_ucmd!().run();
assert!(result.success);
new_ucmd!().succeeds();
}
#[test]
@ -18,8 +17,10 @@ fn test_sync_incorrect_arg() {
fn test_sync_fs() {
let temporary_directory = tempdir().unwrap();
let temporary_path = fs::canonicalize(temporary_directory.path()).unwrap();
let result = new_ucmd!().arg("--file-system").arg(&temporary_path).run();
assert!(result.success);
new_ucmd!()
.arg("--file-system")
.arg(&temporary_path)
.succeeds();
}
#[test]
@ -27,12 +28,14 @@ fn test_sync_data() {
// Todo add a second arg
let temporary_directory = tempdir().unwrap();
let temporary_path = fs::canonicalize(temporary_directory.path()).unwrap();
let result = new_ucmd!().arg("--data").arg(&temporary_path).run();
assert!(result.success);
new_ucmd!().arg("--data").arg(&temporary_path).succeeds();
}
#[test]
fn test_sync_no_existing_files() {
let result = new_ucmd!().arg("--data").arg("do-no-exist").fails();
assert!(result.stderr.contains("error: cannot stat"));
new_ucmd!()
.arg("--data")
.arg("do-no-exist")
.fails()
.stderr_contains("error: cannot stat");
}

View file

@ -226,8 +226,8 @@ fn test_bytes_big() {
.arg(FILE)
.arg("-c")
.arg(format!("{}", N_ARG))
.run()
.stdout;
.succeeds()
.stdout_move_str();
let expected = at.read(EXPECTED_FILE);
assert_eq!(result.len(), expected.len());
@ -340,6 +340,6 @@ fn test_negative_indexing() {
let negative_bytes_index = new_ucmd!().arg("-c").arg("-20").arg(FOOBAR_TXT).run();
assert_eq!(positive_lines_index.stdout, negative_lines_index.stdout);
assert_eq!(positive_bytes_index.stdout, negative_bytes_index.stdout);
assert_eq!(positive_lines_index.stdout(), negative_lines_index.stdout());
assert_eq!(positive_bytes_index.stdout(), negative_bytes_index.stdout());
}

View file

@ -29,6 +29,7 @@ fn set_file_times(at: &AtPath, path: &str, atime: FileTime, mtime: FileTime) {
fn str_to_filetime(format: &str, s: &str) -> FileTime {
let mut tm = time::strptime(s, format).unwrap();
tm.tm_utcoff = time::now().tm_utcoff;
tm.tm_isdst = -1; // Unknown flag DST
let ts = tm.to_timespec();
FileTime::from_unix_time(ts.sec as i64, ts.nsec as u32)
}
@ -352,3 +353,72 @@ fn test_touch_set_date() {
assert_eq!(atime, start_of_year);
assert_eq!(mtime, start_of_year);
}
#[test]
fn test_touch_mtime_dst_succeeds() {
let (at, mut ucmd) = at_and_ucmd!();
let file = "test_touch_set_mtime_dst_succeeds";
ucmd.args(&["-m", "-t", "202103140300", file])
.succeeds()
.no_stderr();
assert!(at.file_exists(file));
let target_time = str_to_filetime("%Y%m%d%H%M", "202103140300");
let (_, mtime) = get_file_times(&at, file);
assert!(target_time == mtime);
}
// is_dst_switch_hour returns true if timespec ts is just before the switch
// to Daylight Saving Time.
// For example, in EST (UTC-5), Timespec { sec: 1583647200, nsec: 0 }
// for March 8 2020 01:00:00 AM
// is just before the switch because on that day clock jumps by 1 hour,
// so 1 minute after 01:59:00 is 03:00:00.
fn is_dst_switch_hour(ts: time::Timespec) -> bool {
let ts_after = ts + time::Duration::hours(1);
let tm = time::at(ts);
let tm_after = time::at(ts_after);
tm_after.tm_hour == tm.tm_hour + 2
}
// get_dstswitch_hour returns date string for which touch -m -t fails.
// For example, in EST (UTC-5), that will be "202003080200" so
// touch -m -t 202003080200 somefile
// fails (that date/time does not exist).
// In other locales it will be a different date/time, and in some locales
// it doesn't exist at all, in which case this function will return None.
fn get_dstswitch_hour() -> Option<String> {
let now = time::now();
// Start from January 1, 2020, 00:00.
let mut tm = time::strptime("20200101-0000", "%Y%m%d-%H%M").unwrap();
tm.tm_isdst = -1;
tm.tm_utcoff = now.tm_utcoff;
let mut ts = tm.to_timespec();
// Loop through all hours in year 2020 until we find the hour just
// before the switch to DST.
for _i in 0..(366 * 24) {
if is_dst_switch_hour(ts) {
let mut tm = time::at(ts);
tm.tm_hour = tm.tm_hour + 1;
let s = time::strftime("%Y%m%d%H%M", &tm).unwrap().to_string();
return Some(s);
}
ts = ts + time::Duration::hours(1);
}
None
}
#[test]
fn test_touch_mtime_dst_fails() {
let (_at, mut ucmd) = at_and_ucmd!();
let file = "test_touch_set_mtime_dst_fails";
match get_dstswitch_hour() {
Some(s) => {
ucmd.args(&["-m", "-t", &s, file]).fails();
}
None => (),
}
}

View file

@ -28,7 +28,7 @@ fn test_version_flag() {
let version_short = new_ucmd!().arg("-V").run();
let version_long = new_ucmd!().arg("--version").run();
assert_eq!(version_short.stdout, version_long.stdout);
assert_eq!(version_short.stdout(), version_long.stdout());
}
#[test]
@ -36,7 +36,7 @@ fn test_help_flag() {
let help_short = new_ucmd!().arg("-h").run();
let help_long = new_ucmd!().arg("--help").run();
assert_eq!(help_short.stdout, help_long.stdout);
assert_eq!(help_short.stdout(), help_long.stdout());
}
#[test]

View file

@ -2,60 +2,41 @@ use crate::common::util::*;
#[test]
fn test_uname_compatible() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("-a").run();
assert!(result.success);
new_ucmd!().arg("-a").succeeds();
}
#[test]
fn test_uname_name() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("-n").run();
assert!(result.success);
new_ucmd!().arg("-n").succeeds();
}
#[test]
fn test_uname_processor() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("-p").run();
assert!(result.success);
assert_eq!(result.stdout.trim_end(), "unknown");
let result = new_ucmd!().arg("-p").succeeds();
assert_eq!(result.stdout_str().trim_end(), "unknown");
}
#[test]
fn test_uname_hwplatform() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("-i").run();
assert!(result.success);
assert_eq!(result.stdout.trim_end(), "unknown");
let result = new_ucmd!().arg("-i").succeeds();
assert_eq!(result.stdout_str().trim_end(), "unknown");
}
#[test]
fn test_uname_machine() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("-m").run();
assert!(result.success);
new_ucmd!().arg("-m").succeeds();
}
#[test]
fn test_uname_kernel_version() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("-v").run();
assert!(result.success);
new_ucmd!().arg("-v").succeeds();
}
#[test]
fn test_uname_kernel() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.arg("-o").run();
assert!(result.success);
let result = ucmd.arg("-o").succeeds();
#[cfg(target_os = "linux")]
assert!(result.stdout.to_lowercase().contains("linux"));
assert!(result.stdout_str().to_lowercase().contains("linux"));
}

View file

@ -4,33 +4,23 @@ use crate::common::util::*;
#[test]
fn test_uptime() {
let result = TestScenario::new(util_name!()).ucmd_keepenv().run();
TestScenario::new(util_name!())
.ucmd_keepenv()
.succeeds()
.stdout_contains("load average:")
.stdout_contains(" up ");
println!("stdout = {}", result.stdout);
println!("stderr = {}", result.stderr);
assert!(result.success);
assert!(result.stdout.contains("load average:"));
assert!(result.stdout.contains(" up "));
// Don't check for users as it doesn't show in some CI
}
#[test]
fn test_uptime_since() {
let scene = TestScenario::new(util_name!());
let result = scene.ucmd().arg("--since").succeeds();
println!("stdout = {}", result.stdout);
println!("stderr = {}", result.stderr);
assert!(result.success);
let re = Regex::new(r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}").unwrap();
assert!(re.is_match(&result.stdout.trim()));
new_ucmd!().arg("--since").succeeds().stdout_matches(&re);
}
#[test]
fn test_failed() {
let (_at, mut ucmd) = at_and_ucmd!();
ucmd.arg("willfail").fails();
new_ucmd!().arg("willfail").fails();
}

View file

@ -3,14 +3,11 @@ use std::env;
#[test]
fn test_users_noarg() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.run();
assert!(result.success);
new_ucmd!().succeeds();
}
#[test]
fn test_users_check_name() {
let result = TestScenario::new(util_name!()).ucmd_keepenv().run();
assert!(result.success);
let result = TestScenario::new(util_name!()).ucmd_keepenv().succeeds();
// Expectation: USER is often set
let key = "USER";
@ -21,9 +18,9 @@ fn test_users_check_name() {
// Check if "users" contains the name of the user
{
println!("username found {}", &username);
println!("result.stdout {}", &result.stdout);
if !&result.stdout.is_empty() {
assert!(result.stdout.contains(&username))
// println!("result.stdout {}", &result.stdout);
if !result.stdout_str().is_empty() {
result.stdout_contains(&username);
}
}
}

View file

@ -1,50 +1,63 @@
use crate::common::util::*;
use std::env;
// Apparently some CI environments have configuration issues, e.g. with 'whoami' and 'id'.
// If we are running inside the CI and "needle" is in "stderr" skipping this test is
// considered okay. If we are not inside the CI this calls assert!(result.success).
//
// From the Logs: "Build (ubuntu-18.04, x86_64-unknown-linux-gnu, feat_os_unix, use-cross)"
// stderr: "whoami: error: failed to get username"
// Maybe: "adduser --uid 1001 username" can put things right?
fn skipping_test_is_okay(result: &CmdResult, needle: &str) -> bool {
if !result.succeeded() {
println!("result.stdout = {}", result.stdout_str());
println!("result.stderr = {}", result.stderr_str());
if is_ci() && result.stderr_str().contains(needle) {
println!("test skipped:");
return true;
} else {
result.success();
}
}
false
}
#[test]
fn test_normal() {
let (_, mut ucmd) = at_and_ucmd!();
let result = ucmd.run();
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
println!("env::var(CI).is_ok() = {}", env::var("CI").is_ok());
for (key, value) in env::vars() {
println!("{}: {}", key, value);
}
if is_ci() && result.stderr.contains("failed to get username") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
// use std::env;
// println!("env::var(CI).is_ok() = {}", env::var("CI").is_ok());
// for (key, value) in env::vars() {
// println!("{}: {}", key, value);
// }
if skipping_test_is_okay(&result, "failed to get username") {
return;
}
assert!(result.success);
assert!(!result.stdout.trim().is_empty());
result.no_stderr();
assert!(!result.stdout_str().trim().is_empty());
}
#[test]
#[cfg(not(windows))]
fn test_normal_compare_id() {
let (_, mut ucmd) = at_and_ucmd!();
let scene = TestScenario::new(util_name!());
let result = ucmd.run();
println!("result.stdout = {}", result.stdout);
println!("result.stderr = {}", result.stderr);
if is_ci() && result.stderr.contains("failed to get username") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
let result_ucmd = scene.ucmd().run();
if skipping_test_is_okay(&result_ucmd, "failed to get username") {
return;
}
assert!(result.success);
let ts = TestScenario::new("id");
let id = ts.cmd("id").arg("-un").run();
if is_ci() && id.stderr.contains("cannot find name for user ID") {
// In the CI, some server are failing to return whoami.
// As seems to be a configuration issue, ignoring it
let result_cmd = scene.cmd("id").arg("-un").run();
if skipping_test_is_okay(&result_cmd, "cannot find name for user ID") {
return;
}
assert_eq!(result.stdout.trim(), id.stdout.trim());
assert_eq!(
result_ucmd.stdout_str().trim(),
result_cmd.stdout_str().trim()
);
}