mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 12:07:46 +00:00
Merge branch 'master' into iss1769
This commit is contained in:
commit
aac79d13b3
81 changed files with 3802 additions and 1438 deletions
|
@ -10,16 +10,16 @@ fn test_output_multi_files_print_all_chars() {
|
|||
.succeeds()
|
||||
.stdout_only(
|
||||
" 1\tabcde$\n 2\tfghij$\n 3\tklmno$\n 4\tpqrst$\n \
|
||||
5\tuvwxyz$\n 6\t^@^A^B^C^D^E^F^G^H^I$\n \
|
||||
7\t^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\\^]^^^_ \
|
||||
!\"#$%&\'()*+,-./0123456789:;\
|
||||
<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~^?M-^@M-^AM-^\
|
||||
BM-^CM-^DM-^EM-^FM-^GM-^HM-^IM-^JM-^KM-^LM-^MM-^NM-^OM-^PM-^QM-^RM-^SM-^TM-^UM-^V\
|
||||
M-^WM-^XM-^YM-^ZM-^[M-^\\M-^]M-^^M-^_M- \
|
||||
M-!M-\"M-#M-$M-%M-&M-\'M-(M-)M-*M-+M-,M--M-.M-/M-0M-1M-2M-3M-4M-5M-6M-7M-8M-9M-:\
|
||||
M-;M-<M-=M->M-?M-@M-AM-BM-CM-DM-EM-FM-GM-HM-IM-JM-KM-LM-MM-NM-OM-PM-QM-RM-SM-TM-U\
|
||||
M-VM-WM-XM-YM-ZM-[M-\\M-]M-^M-_M-`M-aM-bM-cM-dM-eM-fM-gM-hM-iM-jM-kM-lM-mM-nM-oM-\
|
||||
pM-qM-rM-sM-tM-uM-vM-wM-xM-yM-zM-{M-|M-}M-~M-^?",
|
||||
5\tuvwxyz$\n 6\t^@^A^B^C^D^E^F^G^H^I$\n \
|
||||
7\t^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\\^]^^^_ \
|
||||
!\"#$%&\'()*+,-./0123456789:;\
|
||||
<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~^?M-^@M-^AM-^\
|
||||
BM-^CM-^DM-^EM-^FM-^GM-^HM-^IM-^JM-^KM-^LM-^MM-^NM-^OM-^PM-^QM-^RM-^SM-^TM-^UM-^V\
|
||||
M-^WM-^XM-^YM-^ZM-^[M-^\\M-^]M-^^M-^_M- \
|
||||
M-!M-\"M-#M-$M-%M-&M-\'M-(M-)M-*M-+M-,M--M-.M-/M-0M-1M-2M-3M-4M-5M-6M-7M-8M-9M-:\
|
||||
M-;M-<M-=M->M-?M-@M-AM-BM-CM-DM-EM-FM-GM-HM-IM-JM-KM-LM-MM-NM-OM-PM-QM-RM-SM-TM-U\
|
||||
M-VM-WM-XM-YM-ZM-[M-\\M-]M-^M-_M-`M-aM-bM-cM-dM-eM-fM-gM-hM-iM-jM-kM-lM-mM-nM-oM-\
|
||||
pM-qM-rM-sM-tM-uM-vM-wM-xM-yM-zM-{M-|M-}M-~M-^?",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,7 @@ fn test_numbered_lines_no_trailing_newline() {
|
|||
.succeeds()
|
||||
.stdout_only(
|
||||
" 1\ttext without a trailing newlineabcde\n 2\tfghij\n \
|
||||
3\tklmno\n 4\tpqrst\n 5\tuvwxyz\n",
|
||||
3\tklmno\n 4\tpqrst\n 5\tuvwxyz\n",
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ fn test_reference() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_vendor = "apple")]
|
||||
fn test_reference() {
|
||||
new_ucmd!()
|
||||
.arg("-v")
|
||||
|
|
|
@ -1 +1,98 @@
|
|||
// ToDO: add tests
|
||||
use crate::common::util::*;
|
||||
|
||||
#[test]
|
||||
fn test_missing_operand() {
|
||||
let result = new_ucmd!().run();
|
||||
|
||||
assert_eq!(
|
||||
true,
|
||||
result
|
||||
.stderr
|
||||
.starts_with("error: The following required arguments were not provided")
|
||||
);
|
||||
|
||||
assert_eq!(true, result.stderr.contains("<newroot>"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_enter_chroot_fails() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
|
||||
at.mkdir("jail");
|
||||
|
||||
let result = ucmd.arg("jail").run();
|
||||
|
||||
assert_eq!(
|
||||
true,
|
||||
result.stderr.starts_with(
|
||||
"chroot: error: cannot chroot to jail: Operation not permitted (os error 1)"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_such_directory() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
|
||||
at.touch(&at.plus_as_string("a"));
|
||||
|
||||
ucmd.arg("a")
|
||||
.fails()
|
||||
.stderr_is("chroot: error: cannot change root directory to `a`: no such directory");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_user_spec() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
|
||||
at.mkdir("a");
|
||||
|
||||
let result = ucmd.arg("a").arg("--userspec=ARABA:").run();
|
||||
|
||||
assert_eq!(
|
||||
true,
|
||||
result.stderr.starts_with("chroot: error: invalid userspec")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_preference_of_userspec() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let result = scene.cmd("whoami").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
|
||||
return;
|
||||
}
|
||||
println!("result.stdout {}", result.stdout);
|
||||
println!("result.stderr = {}", result.stderr);
|
||||
let username = result.stdout.trim_end();
|
||||
|
||||
let ts = TestScenario::new("id");
|
||||
let result = ts.cmd("id").arg("-g").arg("-n").run();
|
||||
println!("result.stdout {}", result.stdout);
|
||||
println!("result.stderr = {}", result.stderr);
|
||||
|
||||
if is_ci() && result.stderr.contains("cannot find name for user ID") {
|
||||
// In the CI, some server are failing to return id.
|
||||
// As seems to be a configuration issue, ignoring it
|
||||
return;
|
||||
}
|
||||
|
||||
let group_name = result.stdout.trim_end();
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
|
||||
at.mkdir("a");
|
||||
|
||||
let result = ucmd
|
||||
.arg("a")
|
||||
.arg("--user")
|
||||
.arg("fake")
|
||||
.arg("-G")
|
||||
.arg("ABC,DEF")
|
||||
.arg(format!("--userspec={}:{}", username, group_name))
|
||||
.run();
|
||||
|
||||
println!("result.stdout {}", result.stdout);
|
||||
println!("result.stderr = {}", result.stderr);
|
||||
}
|
||||
|
|
|
@ -31,6 +31,12 @@ static TEST_COPY_FROM_FOLDER: &str = "hello_dir_with_file/";
|
|||
static TEST_COPY_FROM_FOLDER_FILE: &str = "hello_dir_with_file/hello_world.txt";
|
||||
static TEST_COPY_TO_FOLDER_NEW: &str = "hello_dir_new";
|
||||
static TEST_COPY_TO_FOLDER_NEW_FILE: &str = "hello_dir_new/hello_world.txt";
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
static TEST_MOUNT_COPY_FROM_FOLDER: &str = "dir_with_mount";
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
static TEST_MOUNT_MOUNTPOINT: &str = "mount";
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
static TEST_MOUNT_OTHER_FILESYSTEM_FILE: &str = "mount/DO_NOT_copy_me.txt";
|
||||
|
||||
#[test]
|
||||
fn test_cp_cp() {
|
||||
|
@ -1001,3 +1007,70 @@ fn test_cp_target_file_dev_null() {
|
|||
|
||||
assert!(at.file_exists(file2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
|
||||
fn test_cp_one_file_system() {
|
||||
use crate::common::util::AtPath;
|
||||
use walkdir::WalkDir;
|
||||
|
||||
let scene = TestScenario::new(util_name!());
|
||||
|
||||
// Test must be run as root (or with `sudo -E`)
|
||||
if scene.cmd("whoami").run().stdout != "root\n" {
|
||||
return;
|
||||
}
|
||||
|
||||
let at = scene.fixtures.clone();
|
||||
let at_src = AtPath::new(&at.plus(TEST_MOUNT_COPY_FROM_FOLDER));
|
||||
let at_dst = AtPath::new(&at.plus(TEST_COPY_TO_FOLDER_NEW));
|
||||
|
||||
// Prepare the mount
|
||||
at_src.mkdir(TEST_MOUNT_MOUNTPOINT);
|
||||
let mountpoint_path = &at_src.plus_as_string(TEST_MOUNT_MOUNTPOINT);
|
||||
|
||||
let _r = scene
|
||||
.cmd("mount")
|
||||
.arg("-t")
|
||||
.arg("tmpfs")
|
||||
.arg("-o")
|
||||
.arg("size=640k") // ought to be enough
|
||||
.arg("tmpfs")
|
||||
.arg(mountpoint_path)
|
||||
.run();
|
||||
assert!(_r.code == Some(0), _r.stderr);
|
||||
|
||||
at_src.touch(TEST_MOUNT_OTHER_FILESYSTEM_FILE);
|
||||
|
||||
// Begin testing -x flag
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg("-rx")
|
||||
.arg(TEST_MOUNT_COPY_FROM_FOLDER)
|
||||
.arg(TEST_COPY_TO_FOLDER_NEW)
|
||||
.run();
|
||||
|
||||
// Ditch the mount before the asserts
|
||||
let _r = scene.cmd("umount").arg(mountpoint_path).run();
|
||||
assert!(_r.code == Some(0), _r.stderr);
|
||||
|
||||
assert!(result.success);
|
||||
assert!(!at_dst.file_exists(TEST_MOUNT_OTHER_FILESYSTEM_FILE));
|
||||
// Check if the other files were copied from the source folder hirerarchy
|
||||
for entry in WalkDir::new(at_src.as_string()) {
|
||||
let entry = entry.unwrap();
|
||||
let relative_src = entry
|
||||
.path()
|
||||
.strip_prefix(at_src.as_string())
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap();
|
||||
|
||||
let ft = entry.file_type();
|
||||
match (ft.is_dir(), ft.is_file(), ft.is_symlink()) {
|
||||
(true, _, _) => assert!(at_dst.dir_exists(relative_src)),
|
||||
(_, true, _) => assert!(at_dst.file_exists(relative_src)),
|
||||
(_, _, _) => panic!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ extern crate regex;
|
|||
|
||||
use self::regex::Regex;
|
||||
use crate::common::util::*;
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
use rust_users::*;
|
||||
|
||||
#[test]
|
||||
fn test_date_email() {
|
||||
|
@ -131,3 +133,92 @@ fn test_date_format_full_day() {
|
|||
let re = Regex::new(r"\S+ \d{4}-\d{2}-\d{2}").unwrap();
|
||||
assert!(re.is_match(&result.stdout.trim()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
fn test_date_set_valid() {
|
||||
if get_effective_uid() == 0 {
|
||||
let (_, mut ucmd) = at_and_ucmd!();
|
||||
let result = ucmd
|
||||
.arg("--set")
|
||||
.arg("2020-03-12 13:30:00+08:00")
|
||||
.succeeds();
|
||||
result.no_stdout().no_stderr();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(any(windows, all(unix, not(target_os = "macos"))))]
|
||||
fn test_date_set_invalid() {
|
||||
let (_, mut ucmd) = at_and_ucmd!();
|
||||
let result = ucmd.arg("--set").arg("123abcd").fails();
|
||||
let result = result.no_stdout();
|
||||
assert!(result.stderr.starts_with("date: invalid date "));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
fn test_date_set_permissions_error() {
|
||||
if !(get_effective_uid() == 0 || is_wsl()) {
|
||||
let (_, mut ucmd) = at_and_ucmd!();
|
||||
let result = ucmd.arg("--set").arg("2020-03-11 21:45:00+08:00").fails();
|
||||
let result = result.no_stdout();
|
||||
assert!(result.stderr.starts_with("date: cannot set date: "));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(target_os = "macos")]
|
||||
fn test_date_set_mac_unavailable() {
|
||||
let (_, mut ucmd) = at_and_ucmd!();
|
||||
let result = ucmd.arg("--set").arg("2020-03-11 21:45:00+08:00").fails();
|
||||
let result = result.no_stdout();
|
||||
assert!(result
|
||||
.stderr
|
||||
.starts_with("date: setting the date is not supported by macOS"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
/// TODO: expected to fail currently; change to succeeds() when required.
|
||||
fn test_date_set_valid_2() {
|
||||
if get_effective_uid() == 0 {
|
||||
let (_, mut ucmd) = at_and_ucmd!();
|
||||
let result = ucmd
|
||||
.arg("--set")
|
||||
.arg("Sat 20 Mar 2021 14:53:01 AWST")
|
||||
.fails();
|
||||
let result = result.no_stdout();
|
||||
assert!(result.stderr.starts_with("date: invalid date "));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
/// TODO: expected to fail currently; change to succeeds() when required.
|
||||
fn test_date_set_valid_3() {
|
||||
if get_effective_uid() == 0 {
|
||||
let (_, mut ucmd) = at_and_ucmd!();
|
||||
let result = ucmd
|
||||
.arg("--set")
|
||||
.arg("Sat 20 Mar 2021 14:53:01") // Local timezone
|
||||
.fails();
|
||||
let result = result.no_stdout();
|
||||
assert!(result.stderr.starts_with("date: invalid date "));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
/// TODO: expected to fail currently; change to succeeds() when required.
|
||||
fn test_date_set_valid_4() {
|
||||
if get_effective_uid() == 0 {
|
||||
let (_, mut ucmd) = at_and_ucmd!();
|
||||
let result = ucmd
|
||||
.arg("--set")
|
||||
.arg("2020-03-11 21:45:00") // Local timezone
|
||||
.fails();
|
||||
let result = result.no_stdout();
|
||||
assert!(result.stderr.starts_with("date: invalid date "));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ fn test_du_basics() {
|
|||
assert!(result.success);
|
||||
assert_eq!(result.stderr, "");
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_vendor = "apple")]
|
||||
fn _du_basics(s: String) {
|
||||
let answer = "32\t./subdir
|
||||
8\t./subdir/deeper
|
||||
|
@ -21,7 +21,7 @@ fn _du_basics(s: String) {
|
|||
";
|
||||
assert_eq!(s, answer);
|
||||
}
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
#[cfg(not(target_vendor = "apple"))]
|
||||
fn _du_basics(s: String) {
|
||||
let answer = "28\t./subdir
|
||||
8\t./subdir/deeper
|
||||
|
@ -41,11 +41,11 @@ fn test_du_basics_subdir() {
|
|||
_du_basics_subdir(result.stdout);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_vendor = "apple")]
|
||||
fn _du_basics_subdir(s: String) {
|
||||
assert_eq!(s, "4\tsubdir/deeper\n");
|
||||
}
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
#[cfg(not(target_vendor = "apple"))]
|
||||
fn _du_basics_subdir(s: String) {
|
||||
// MS-WSL linux has altered expected output
|
||||
if !is_wsl() {
|
||||
|
@ -80,12 +80,12 @@ fn test_du_soft_link() {
|
|||
_du_soft_link(result.stdout);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_vendor = "apple")]
|
||||
fn _du_soft_link(s: String) {
|
||||
// 'macos' host variants may have `du` output variation for soft links
|
||||
assert!((s == "12\tsubdir/links\n") || (s == "16\tsubdir/links\n"));
|
||||
}
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
#[cfg(not(target_vendor = "apple"))]
|
||||
fn _du_soft_link(s: String) {
|
||||
// MS-WSL linux has altered expected output
|
||||
if !is_wsl() {
|
||||
|
@ -109,11 +109,11 @@ fn test_du_hard_link() {
|
|||
_du_hard_link(result.stdout);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_vendor = "apple")]
|
||||
fn _du_hard_link(s: String) {
|
||||
assert_eq!(s, "12\tsubdir/links\n")
|
||||
}
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
#[cfg(not(target_vendor = "apple"))]
|
||||
fn _du_hard_link(s: String) {
|
||||
// MS-WSL linux has altered expected output
|
||||
if !is_wsl() {
|
||||
|
@ -133,11 +133,11 @@ fn test_du_d_flag() {
|
|||
_du_d_flag(result.stdout);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[cfg(target_vendor = "apple")]
|
||||
fn _du_d_flag(s: String) {
|
||||
assert_eq!(s, "16\t./subdir\n20\t./\n");
|
||||
}
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
#[cfg(not(target_vendor = "apple"))]
|
||||
fn _du_d_flag(s: String) {
|
||||
// MS-WSL linux has altered expected output
|
||||
if !is_wsl() {
|
||||
|
|
|
@ -173,3 +173,58 @@ fn test_disable_escapes() {
|
|||
.succeeds()
|
||||
.stdout_only(format!("{}\n", input_str));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hyphen_value() {
|
||||
new_ucmd!().arg("-abc").succeeds().stdout_is("-abc\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiple_hyphen_values() {
|
||||
new_ucmd!()
|
||||
.args(&["-abc", "-def", "-edf"])
|
||||
.succeeds()
|
||||
.stdout_is("-abc -def -edf\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hyphen_values_inside_string() {
|
||||
new_ucmd!()
|
||||
.arg("'\"\n'CXXFLAGS=-g -O2'\n\"'")
|
||||
.succeeds()
|
||||
.stdout
|
||||
.contains("CXXFLAGS");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hyphen_values_at_start() {
|
||||
let result = new_ucmd!()
|
||||
.arg("-E")
|
||||
.arg("-test")
|
||||
.arg("araba")
|
||||
.arg("-merci")
|
||||
.run();
|
||||
|
||||
assert!(result.success);
|
||||
assert_eq!(false, result.stdout.contains("-E"));
|
||||
assert_eq!(result.stdout, "-test araba -merci\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hyphen_values_between() {
|
||||
let result = new_ucmd!().arg("test").arg("-E").arg("araba").run();
|
||||
|
||||
assert!(result.success);
|
||||
assert_eq!(result.stdout, "test -E araba\n");
|
||||
|
||||
let result = new_ucmd!()
|
||||
.arg("dumdum ")
|
||||
.arg("dum dum dum")
|
||||
.arg("-e")
|
||||
.arg("dum")
|
||||
.run();
|
||||
|
||||
assert!(result.success);
|
||||
assert_eq!(result.stdout, "dumdum dum dum dum -e dum\n");
|
||||
assert_eq!(true, result.stdout.contains("-e"));
|
||||
}
|
||||
|
|
|
@ -86,6 +86,14 @@ fn test_verbose() {
|
|||
.stdout_is_fixture("lorem_ipsum_verbose.expected");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero_terminated() {
|
||||
new_ucmd!()
|
||||
.args(&["-z", "zero_terminated.txt"])
|
||||
.run()
|
||||
.stdout_is_fixture("zero_terminated.expected");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_spams_newline() {
|
||||
|
@ -159,3 +167,15 @@ fn test_bug_in_negative_zero_lines() {
|
|||
//GNU Head returns "a\nb\n"
|
||||
.stdout_is("");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_such_file_or_directory() {
|
||||
let result = new_ucmd!().arg("no_such_file.toml").run();
|
||||
|
||||
assert_eq!(
|
||||
true,
|
||||
result
|
||||
.stderr
|
||||
.contains("cannot open 'no_such_file.toml' for reading: No such file or directory")
|
||||
)
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ fn test_hostname() {
|
|||
}
|
||||
|
||||
// FixME: fails for "MacOS"
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
#[cfg(not(target_vendor = "apple"))]
|
||||
#[test]
|
||||
fn test_hostname_ip() {
|
||||
let result = new_ucmd!().arg("-i").run();
|
||||
|
|
|
@ -17,9 +17,9 @@ fn test_install_help() {
|
|||
#[test]
|
||||
fn test_install_basic() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let dir = "test_install_target_dir_dir_a";
|
||||
let file1 = "test_install_target_dir_file_a1";
|
||||
let file2 = "test_install_target_dir_file_a2";
|
||||
let dir = "target_dir";
|
||||
let file1 = "source_file1";
|
||||
let file2 = "source_file2";
|
||||
|
||||
at.touch(file1);
|
||||
at.touch(file2);
|
||||
|
@ -34,7 +34,7 @@ fn test_install_basic() {
|
|||
|
||||
#[test]
|
||||
fn test_install_twice_dir() {
|
||||
let dir = "test_install_target_dir_dir_a";
|
||||
let dir = "dir";
|
||||
let scene = TestScenario::new(util_name!());
|
||||
|
||||
scene.ucmd().arg("-d").arg(dir).succeeds();
|
||||
|
@ -47,9 +47,9 @@ fn test_install_twice_dir() {
|
|||
#[test]
|
||||
fn test_install_failing_not_dir() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file1 = "test_install_target_dir_file_a1";
|
||||
let file2 = "test_install_target_dir_file_a2";
|
||||
let file3 = "test_install_target_dir_file_a3";
|
||||
let file1 = "file1";
|
||||
let file2 = "file2";
|
||||
let file3 = "file3";
|
||||
|
||||
at.touch(file1);
|
||||
at.touch(file2);
|
||||
|
@ -66,8 +66,8 @@ fn test_install_failing_not_dir() {
|
|||
#[test]
|
||||
fn test_install_unimplemented_arg() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let dir = "test_install_target_dir_dir_b";
|
||||
let file = "test_install_target_dir_file_b";
|
||||
let dir = "target_dir";
|
||||
let file = "source_file";
|
||||
let context_arg = "--context";
|
||||
|
||||
at.touch(file);
|
||||
|
@ -86,9 +86,9 @@ fn test_install_unimplemented_arg() {
|
|||
#[test]
|
||||
fn test_install_component_directories() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let component1 = "test_install_target_dir_component_c1";
|
||||
let component2 = "test_install_target_dir_component_c2";
|
||||
let component3 = "test_install_target_dir_component_c3";
|
||||
let component1 = "component1";
|
||||
let component2 = "component2";
|
||||
let component3 = "component3";
|
||||
let directories_arg = "-d";
|
||||
|
||||
ucmd.args(&[directories_arg, component1, component2, component3])
|
||||
|
@ -104,10 +104,10 @@ fn test_install_component_directories() {
|
|||
fn test_install_mode_numeric() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
let dir = "test_install_target_dir_dir_e";
|
||||
let dir2 = "test_install_target_dir_dir_e2";
|
||||
let dir = "dir1";
|
||||
let dir2 = "dir2";
|
||||
|
||||
let file = "test_install_target_dir_file_e";
|
||||
let file = "file";
|
||||
let mode_arg = "--mode=333";
|
||||
|
||||
at.touch(file);
|
||||
|
@ -145,8 +145,8 @@ fn test_install_mode_numeric() {
|
|||
#[test]
|
||||
fn test_install_mode_symbolic() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let dir = "test_install_target_dir_dir_f";
|
||||
let file = "test_install_target_dir_file_f";
|
||||
let dir = "target_dir";
|
||||
let file = "source_file";
|
||||
let mode_arg = "--mode=o+wx";
|
||||
|
||||
at.touch(file);
|
||||
|
@ -163,8 +163,8 @@ fn test_install_mode_symbolic() {
|
|||
#[test]
|
||||
fn test_install_mode_failing() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let dir = "test_install_target_dir_dir_g";
|
||||
let file = "test_install_target_dir_file_g";
|
||||
let dir = "target_dir";
|
||||
let file = "source_file";
|
||||
let mode_arg = "--mode=999";
|
||||
|
||||
at.touch(file);
|
||||
|
@ -185,7 +185,7 @@ fn test_install_mode_failing() {
|
|||
#[test]
|
||||
fn test_install_mode_directories() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let component = "test_install_target_dir_component_h";
|
||||
let component = "component";
|
||||
let directories_arg = "-d";
|
||||
let mode_arg = "--mode=333";
|
||||
|
||||
|
@ -203,8 +203,8 @@ fn test_install_mode_directories() {
|
|||
#[test]
|
||||
fn test_install_target_file() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file1 = "test_install_target_file_file_i1";
|
||||
let file2 = "test_install_target_file_file_i2";
|
||||
let file1 = "source_file";
|
||||
let file2 = "target_file";
|
||||
|
||||
at.touch(file1);
|
||||
at.touch(file2);
|
||||
|
@ -217,8 +217,8 @@ fn test_install_target_file() {
|
|||
#[test]
|
||||
fn test_install_target_new_file() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file = "test_install_target_new_filer_file_j";
|
||||
let dir = "test_install_target_new_file_dir_j";
|
||||
let file = "file";
|
||||
let dir = "target_dir";
|
||||
|
||||
at.touch(file);
|
||||
at.mkdir(dir);
|
||||
|
@ -234,8 +234,8 @@ fn test_install_target_new_file() {
|
|||
#[test]
|
||||
fn test_install_target_new_file_with_group() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file = "test_install_target_new_filer_file_j";
|
||||
let dir = "test_install_target_new_file_dir_j";
|
||||
let file = "file";
|
||||
let dir = "target_dir";
|
||||
let gid = get_effective_gid();
|
||||
|
||||
at.touch(file);
|
||||
|
@ -264,8 +264,8 @@ fn test_install_target_new_file_with_group() {
|
|||
#[test]
|
||||
fn test_install_target_new_file_with_owner() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file = "test_install_target_new_filer_file_j";
|
||||
let dir = "test_install_target_new_file_dir_j";
|
||||
let file = "file";
|
||||
let dir = "target_dir";
|
||||
let uid = get_effective_uid();
|
||||
|
||||
at.touch(file);
|
||||
|
@ -294,9 +294,9 @@ fn test_install_target_new_file_with_owner() {
|
|||
#[test]
|
||||
fn test_install_target_new_file_failing_nonexistent_parent() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file1 = "test_install_target_new_file_failing_file_k1";
|
||||
let file2 = "test_install_target_new_file_failing_file_k2";
|
||||
let dir = "test_install_target_new_file_failing_dir_k";
|
||||
let file1 = "source_file";
|
||||
let file2 = "target_file";
|
||||
let dir = "target_dir";
|
||||
|
||||
at.touch(file1);
|
||||
|
||||
|
@ -312,8 +312,8 @@ fn test_install_target_new_file_failing_nonexistent_parent() {
|
|||
#[test]
|
||||
fn test_install_preserve_timestamps() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file1 = "test_install_target_dir_file_a1";
|
||||
let file2 = "test_install_target_dir_file_a2";
|
||||
let file1 = "source_file";
|
||||
let file2 = "target_file";
|
||||
at.touch(file1);
|
||||
|
||||
ucmd.arg(file1).arg(file2).arg("-p").succeeds().no_stderr();
|
||||
|
@ -338,8 +338,8 @@ fn test_install_preserve_timestamps() {
|
|||
#[test]
|
||||
fn test_install_copy_file() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file1 = "test_install_target_dir_file_a1";
|
||||
let file2 = "test_install_target_dir_file_a2";
|
||||
let file1 = "source_file";
|
||||
let file2 = "target_file";
|
||||
|
||||
at.touch(file1);
|
||||
ucmd.arg(file1).arg(file2).succeeds().no_stderr();
|
||||
|
@ -353,8 +353,57 @@ fn test_install_copy_file() {
|
|||
fn test_install_target_file_dev_null() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file1 = "/dev/null";
|
||||
let file2 = "test_install_target_file_file_i2";
|
||||
let file2 = "target_file";
|
||||
|
||||
ucmd.arg(file1).arg(file2).succeeds().no_stderr();
|
||||
assert!(at.file_exists(file2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_nested_paths_copy_file() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file1 = "source_file";
|
||||
let dir1 = "source_dir";
|
||||
let dir2 = "target_dir";
|
||||
|
||||
at.mkdir(dir1);
|
||||
at.mkdir(dir2);
|
||||
at.touch(&format!("{}/{}", dir1, file1));
|
||||
|
||||
ucmd.arg(format!("{}/{}", dir1, file1))
|
||||
.arg(dir2)
|
||||
.succeeds()
|
||||
.no_stderr();
|
||||
assert!(at.file_exists(&format!("{}/{}", dir2, file1)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_failing_omitting_directory() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file1 = "source_file";
|
||||
let dir1 = "source_dir";
|
||||
let dir2 = "target_dir";
|
||||
|
||||
at.mkdir(dir1);
|
||||
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"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_install_failing_no_such_file() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let file1 = "source_file";
|
||||
let file2 = "inexistent_file";
|
||||
let dir1 = "target_dir";
|
||||
|
||||
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"));
|
||||
}
|
||||
|
|
|
@ -57,6 +57,200 @@ fn test_ls_a() {
|
|||
assert!(!result.stdout.contains(".."));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ls_width() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.touch(&at.plus_as_string("test-width-1"));
|
||||
at.touch(&at.plus_as_string("test-width-2"));
|
||||
at.touch(&at.plus_as_string("test-width-3"));
|
||||
at.touch(&at.plus_as_string("test-width-4"));
|
||||
|
||||
for option in &["-w 100", "-w=100", "--width=100", "--width 100"] {
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.args(&option.split(" ").collect::<Vec<_>>())
|
||||
.run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert_eq!(
|
||||
result.stdout,
|
||||
"test-width-1 test-width-2 test-width-3 test-width-4\n",
|
||||
)
|
||||
}
|
||||
|
||||
for option in &["-w 50", "-w=50", "--width=50", "--width 50"] {
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.args(&option.split(" ").collect::<Vec<_>>())
|
||||
.run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert_eq!(
|
||||
result.stdout,
|
||||
"test-width-1 test-width-3\ntest-width-2 test-width-4\n",
|
||||
)
|
||||
}
|
||||
|
||||
for option in &[
|
||||
"-w 25",
|
||||
"-w=25",
|
||||
"--width=25",
|
||||
"--width 25",
|
||||
"-w 0",
|
||||
"-w=0",
|
||||
"--width=0",
|
||||
"--width 0",
|
||||
] {
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.args(&option.split(" ").collect::<Vec<_>>())
|
||||
.run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert_eq!(
|
||||
result.stdout,
|
||||
"test-width-1\ntest-width-2\ntest-width-3\ntest-width-4\n",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ls_columns() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.touch(&at.plus_as_string("test-columns-1"));
|
||||
at.touch(&at.plus_as_string("test-columns-2"));
|
||||
at.touch(&at.plus_as_string("test-columns-3"));
|
||||
at.touch(&at.plus_as_string("test-columns-4"));
|
||||
|
||||
// Columns is the default
|
||||
let result = scene.ucmd().run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
|
||||
#[cfg(not(windows))]
|
||||
assert_eq!(
|
||||
result.stdout,
|
||||
"test-columns-1\ntest-columns-2\ntest-columns-3\ntest-columns-4\n"
|
||||
);
|
||||
#[cfg(windows)]
|
||||
assert_eq!(
|
||||
result.stdout,
|
||||
"test-columns-1 test-columns-2 test-columns-3 test-columns-4\n"
|
||||
);
|
||||
|
||||
for option in &["-C", "--format=columns"] {
|
||||
let result = scene.ucmd().arg(option).run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
#[cfg(not(windows))]
|
||||
assert_eq!(
|
||||
result.stdout,
|
||||
"test-columns-1\ntest-columns-2\ntest-columns-3\ntest-columns-4\n"
|
||||
);
|
||||
#[cfg(windows)]
|
||||
assert_eq!(
|
||||
result.stdout,
|
||||
"test-columns-1 test-columns-2 test-columns-3 test-columns-4\n"
|
||||
);
|
||||
}
|
||||
|
||||
for option in &["-C", "--format=columns"] {
|
||||
let result = scene.ucmd().arg("-w=40").arg(option).run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
assert_eq!(
|
||||
result.stdout,
|
||||
"test-columns-1 test-columns-3\ntest-columns-2 test-columns-4\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ls_across() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.touch(&at.plus_as_string("test-across-1"));
|
||||
at.touch(&at.plus_as_string("test-across-2"));
|
||||
at.touch(&at.plus_as_string("test-across-3"));
|
||||
at.touch(&at.plus_as_string("test-across-4"));
|
||||
|
||||
for option in &["-x", "--format=across"] {
|
||||
let result = scene.ucmd().arg(option).succeeds();
|
||||
// Because the test terminal has width 0, this is the same output as
|
||||
// the columns option.
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
if cfg!(unix) {
|
||||
assert_eq!(
|
||||
result.stdout,
|
||||
"test-across-1\ntest-across-2\ntest-across-3\ntest-across-4\n"
|
||||
);
|
||||
} else {
|
||||
assert_eq!(
|
||||
result.stdout,
|
||||
"test-across-1 test-across-2 test-across-3 test-across-4\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for option in &["-x", "--format=across"] {
|
||||
let result = scene.ucmd().arg("-w=30").arg(option).run();
|
||||
// Because the test terminal has width 0, this is the same output as
|
||||
// the columns option.
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert_eq!(
|
||||
result.stdout,
|
||||
"test-across-1 test-across-2\ntest-across-3 test-across-4\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ls_commas() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.touch(&at.plus_as_string("test-commas-1"));
|
||||
at.touch(&at.plus_as_string("test-commas-2"));
|
||||
at.touch(&at.plus_as_string("test-commas-3"));
|
||||
at.touch(&at.plus_as_string("test-commas-4"));
|
||||
|
||||
for option in &["-m", "--format=commas"] {
|
||||
let result = scene.ucmd().arg(option).succeeds();
|
||||
if cfg!(unix) {
|
||||
assert_eq!(
|
||||
result.stdout,
|
||||
"test-commas-1,\ntest-commas-2,\ntest-commas-3,\ntest-commas-4\n"
|
||||
);
|
||||
} else {
|
||||
assert_eq!(
|
||||
result.stdout,
|
||||
"test-commas-1, test-commas-2, test-commas-3, test-commas-4\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for option in &["-m", "--format=commas"] {
|
||||
let result = scene.ucmd().arg("-w=30").arg(option).succeeds();
|
||||
assert_eq!(
|
||||
result.stdout,
|
||||
"test-commas-1, test-commas-2,\ntest-commas-3, test-commas-4\n"
|
||||
);
|
||||
}
|
||||
for option in &["-m", "--format=commas"] {
|
||||
let result = scene.ucmd().arg("-w=45").arg(option).succeeds();
|
||||
assert_eq!(
|
||||
result.stdout,
|
||||
"test-commas-1, test-commas-2, test-commas-3,\ntest-commas-4\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ls_long() {
|
||||
#[cfg(not(windows))]
|
||||
|
@ -71,16 +265,20 @@ fn test_ls_long() {
|
|||
}
|
||||
}
|
||||
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.touch(&at.plus_as_string("test-long"));
|
||||
let result = ucmd.arg("-l").arg("test-long").succeeds();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
#[cfg(not(windows))]
|
||||
assert!(result.stdout.contains("-rw-rw-r--"));
|
||||
|
||||
#[cfg(windows)]
|
||||
assert!(result.stdout.contains("---------- 1 somebody somegroup"));
|
||||
for arg in &["-l", "--long", "--format=long", "--format=verbose"] {
|
||||
let result = scene.ucmd().arg(arg).arg("test-long").succeeds();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
#[cfg(not(windows))]
|
||||
assert!(result.stdout.contains("-rw-rw-r--"));
|
||||
|
||||
#[cfg(windows)]
|
||||
assert!(result.stdout.contains("---------- 1 somebody somegroup"));
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
|
@ -90,6 +288,126 @@ fn test_ls_long() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ls_long_formats() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.touch(&at.plus_as_string("test-long-formats"));
|
||||
|
||||
// Regex for three names, so all of author, group and owner
|
||||
let re_three = Regex::new(r"[xrw-]{9} \d ([-0-9_a-z]+ ){3}0").unwrap();
|
||||
|
||||
// Regex for two names, either:
|
||||
// - group and owner
|
||||
// - author and owner
|
||||
// - author and group
|
||||
let re_two = Regex::new(r"[xrw-]{9} \d ([-0-9_a-z]+ ){2}0").unwrap();
|
||||
|
||||
// Regex for one name: author, group or owner
|
||||
let re_one = Regex::new(r"[xrw-]{9} \d [-0-9_a-z]+ 0").unwrap();
|
||||
|
||||
// Regex for no names
|
||||
let re_zero = Regex::new(r"[xrw-]{9} \d 0").unwrap();
|
||||
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg("-l")
|
||||
.arg("--author")
|
||||
.arg("test-long-formats")
|
||||
.run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(re_three.is_match(&result.stdout));
|
||||
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg("-l1")
|
||||
.arg("--author")
|
||||
.arg("test-long-formats")
|
||||
.run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(re_three.is_match(&result.stdout));
|
||||
|
||||
for arg in &[
|
||||
"-l", // only group and owner
|
||||
"-g --author", // only author and group
|
||||
"-o --author", // only author and owner
|
||||
"-lG --author", // only author and owner
|
||||
"-l --no-group --author", // only author and owner
|
||||
] {
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.args(&arg.split(" ").collect::<Vec<_>>())
|
||||
.arg("test-long-formats")
|
||||
.succeeds();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(re_two.is_match(&result.stdout));
|
||||
}
|
||||
|
||||
for arg in &[
|
||||
"-g", // only group
|
||||
"-gl", // only group
|
||||
"-o", // only owner
|
||||
"-ol", // only owner
|
||||
"-oG", // only owner
|
||||
"-lG", // only owner
|
||||
"-l --no-group", // only owner
|
||||
"-gG --author", // only author
|
||||
] {
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.args(&arg.split(" ").collect::<Vec<_>>())
|
||||
.arg("test-long-formats")
|
||||
.succeeds();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(re_one.is_match(&result.stdout));
|
||||
}
|
||||
|
||||
for arg in &[
|
||||
"-og",
|
||||
"-ogl",
|
||||
"-lgo",
|
||||
"-gG",
|
||||
"-g --no-group",
|
||||
"-og --no-group",
|
||||
"-og --format=long",
|
||||
"-ogCl",
|
||||
"-og --format=vertical -l",
|
||||
"-og1",
|
||||
"-og1l",
|
||||
] {
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.args(&arg.split(" ").collect::<Vec<_>>())
|
||||
.arg("test-long-formats")
|
||||
.succeeds();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(re_zero.is_match(&result.stdout));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ls_oneline() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.touch(&at.plus_as_string("test-oneline-1"));
|
||||
at.touch(&at.plus_as_string("test-oneline-2"));
|
||||
|
||||
// Bit of a weird situation: in the tests oneline and columns have the same output,
|
||||
// except on Windows.
|
||||
for option in &["-1", "--format=single-column"] {
|
||||
let result = scene.ucmd().arg(option).run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
assert_eq!(result.stdout, "test-oneline-1\ntest-oneline-2\n");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ls_deref() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
|
@ -166,27 +484,55 @@ fn test_ls_order_size() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_ls_order_creation() {
|
||||
fn test_ls_long_ctime() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
at.touch("test-long-ctime-1");
|
||||
let result = scene.ucmd().arg("-lc").succeeds();
|
||||
|
||||
// Should show the time on Unix, but question marks on windows.
|
||||
#[cfg(unix)]
|
||||
assert!(result.stdout.contains(":"));
|
||||
#[cfg(not(unix))]
|
||||
assert!(result.stdout.contains("???"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ls_order_time() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
at.touch("test-1");
|
||||
at.append("test-1", "1");
|
||||
sleep(Duration::from_millis(500));
|
||||
sleep(Duration::from_millis(100));
|
||||
at.touch("test-2");
|
||||
at.append("test-2", "22");
|
||||
sleep(Duration::from_millis(500));
|
||||
|
||||
sleep(Duration::from_millis(100));
|
||||
at.touch("test-3");
|
||||
at.append("test-3", "333");
|
||||
sleep(Duration::from_millis(500));
|
||||
sleep(Duration::from_millis(100));
|
||||
at.touch("test-4");
|
||||
at.append("test-4", "4444");
|
||||
sleep(Duration::from_millis(100));
|
||||
|
||||
// Read test-3, only changing access time
|
||||
at.read("test-3");
|
||||
|
||||
// Set permissions of test-2, only changing ctime
|
||||
std::fs::set_permissions(
|
||||
at.plus_as_string("test-2"),
|
||||
at.metadata("test-2").permissions(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let result = scene.ucmd().arg("-al").run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
|
||||
// ctime was changed at write, so the order is 4 3 2 1
|
||||
let result = scene.ucmd().arg("-t").run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
|
@ -196,7 +542,7 @@ fn test_ls_order_creation() {
|
|||
#[cfg(windows)]
|
||||
assert_eq!(result.stdout, "test-4 test-3 test-2 test-1\n");
|
||||
|
||||
let result = scene.ucmd().arg("-t").arg("-r").run();
|
||||
let result = scene.ucmd().arg("-tr").run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
|
@ -204,6 +550,41 @@ fn test_ls_order_creation() {
|
|||
assert_eq!(result.stdout, "test-1\ntest-2\ntest-3\ntest-4\n");
|
||||
#[cfg(windows)]
|
||||
assert_eq!(result.stdout, "test-1 test-2 test-3 test-4\n");
|
||||
|
||||
// 3 was accessed last in the read
|
||||
// So the order should be 2 3 4 1
|
||||
let result = scene.ucmd().arg("-tu").run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
let file3_access = at.open("test-3").metadata().unwrap().accessed().unwrap();
|
||||
let file4_access = at.open("test-4").metadata().unwrap().accessed().unwrap();
|
||||
if file3_access > file4_access {
|
||||
if cfg!(not(windows)) {
|
||||
assert_eq!(result.stdout, "test-3\ntest-4\ntest-2\ntest-1\n");
|
||||
} else {
|
||||
assert_eq!(result.stdout, "test-3 test-4 test-2 test-1\n");
|
||||
}
|
||||
} else {
|
||||
// Access time does not seem to be set on Windows and some other
|
||||
// systems so the order is 4 3 2 1
|
||||
if cfg!(not(windows)) {
|
||||
assert_eq!(result.stdout, "test-4\ntest-3\ntest-2\ntest-1\n");
|
||||
} else {
|
||||
assert_eq!(result.stdout, "test-4 test-3 test-2 test-1\n");
|
||||
}
|
||||
}
|
||||
|
||||
// test-2 had the last ctime change when the permissions were set
|
||||
// So the order should be 2 4 3 1
|
||||
#[cfg(unix)]
|
||||
{
|
||||
let result = scene.ucmd().arg("-tc").run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
assert_eq!(result.stdout, "test-2\ntest-4\ntest-3\ntest-1\n");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -270,45 +651,197 @@ fn test_ls_recursive() {
|
|||
assert!(result.stdout.contains("a\\b:\nb"));
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn test_ls_ls_color() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.mkdir("a");
|
||||
at.mkdir("a/nested_dir");
|
||||
at.mkdir("z");
|
||||
at.touch(&at.plus_as_string("a/a"));
|
||||
scene.ucmd().arg("--color").succeeds();
|
||||
scene.ucmd().arg("--color=always").succeeds();
|
||||
scene.ucmd().arg("--color=never").succeeds();
|
||||
scene.ucmd().arg("--color").arg("a").succeeds();
|
||||
scene.ucmd().arg("--color=always").arg("a/a").succeeds();
|
||||
scene.ucmd().arg("--color=never").arg("z").succeeds();
|
||||
at.touch(&at.plus_as_string("a/nested_file"));
|
||||
at.touch("test-color");
|
||||
|
||||
let a_with_colors = "\x1b[01;34ma\x1b[0m";
|
||||
let z_with_colors = "\x1b[01;34mz\x1b[0m";
|
||||
let nested_dir_with_colors = "\x1b[01;34mnested_dir\x1b[0m";
|
||||
|
||||
// Color is disabled by default
|
||||
let result = scene.ucmd().succeeds();
|
||||
assert!(!result.stdout.contains(a_with_colors));
|
||||
assert!(!result.stdout.contains(z_with_colors));
|
||||
|
||||
// Color should be enabled
|
||||
let result = scene.ucmd().arg("--color").succeeds();
|
||||
assert!(result.stdout.contains(a_with_colors));
|
||||
assert!(result.stdout.contains(z_with_colors));
|
||||
|
||||
// Color should be enabled
|
||||
let result = scene.ucmd().arg("--color=always").succeeds();
|
||||
assert!(result.stdout.contains(a_with_colors));
|
||||
assert!(result.stdout.contains(z_with_colors));
|
||||
|
||||
// Color should be disabled
|
||||
let result = scene.ucmd().arg("--color=never").succeeds();
|
||||
assert!(!result.stdout.contains(a_with_colors));
|
||||
assert!(!result.stdout.contains(z_with_colors));
|
||||
|
||||
// Nested dir should be shown and colored
|
||||
let result = scene.ucmd().arg("--color").arg("a").succeeds();
|
||||
assert!(result.stdout.contains(nested_dir_with_colors));
|
||||
|
||||
// Color has no effect
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg("--color=always")
|
||||
.arg("a/nested_file")
|
||||
.succeeds();
|
||||
assert!(result.stdout.contains("a/nested_file\n"));
|
||||
|
||||
// No output
|
||||
let result = scene.ucmd().arg("--color=never").arg("z").succeeds();
|
||||
assert_eq!(result.stdout, "");
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "macos", target_os = "windows")))] // Truncate not available on mac or win
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn test_ls_human() {
|
||||
fn test_ls_inode() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let file = "test_human";
|
||||
let result = scene.cmd("truncate").arg("-s").arg("+1000").arg(file).run();
|
||||
let at = &scene.fixtures;
|
||||
|
||||
let file = "test_inode";
|
||||
at.touch(file);
|
||||
|
||||
let re_short = Regex::new(r" *(\d+) test_inode").unwrap();
|
||||
let re_long = Regex::new(r" *(\d+) [xrw-]{10} \d .+ test_inode").unwrap();
|
||||
|
||||
let result = scene.ucmd().arg("test_inode").arg("-i").run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
let result = scene.ucmd().arg("-hl").arg(file).run();
|
||||
assert!(re_short.is_match(&result.stdout));
|
||||
let inode_short = re_short
|
||||
.captures(&result.stdout)
|
||||
.unwrap()
|
||||
.get(1)
|
||||
.unwrap()
|
||||
.as_str();
|
||||
|
||||
let result = scene.ucmd().arg("test_inode").run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(!re_short.is_match(&result.stdout));
|
||||
assert!(!result.stdout.contains(inode_short));
|
||||
|
||||
let result = scene.ucmd().arg("-li").arg("test_inode").run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(re_long.is_match(&result.stdout));
|
||||
let inode_long = re_long
|
||||
.captures(&result.stdout)
|
||||
.unwrap()
|
||||
.get(1)
|
||||
.unwrap()
|
||||
.as_str();
|
||||
|
||||
let result = scene.ucmd().arg("-l").arg("test_inode").run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(!re_long.is_match(&result.stdout));
|
||||
assert!(!result.stdout.contains(inode_long));
|
||||
|
||||
assert_eq!(inode_short, inode_long)
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_vendor = "apple", target_os = "windows")))] // Truncate not available on mac or win
|
||||
#[test]
|
||||
fn test_ls_human_si() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let file1 = "test_human-1";
|
||||
let result = scene
|
||||
.cmd("truncate")
|
||||
.arg("-s")
|
||||
.arg("+1000")
|
||||
.arg(file1)
|
||||
.run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
|
||||
let result = scene.ucmd().arg("-hl").arg(file1).run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
assert!(result.stdout.contains("1.00K"));
|
||||
assert!(result.stdout.contains(" 1000 "));
|
||||
|
||||
let result = scene.ucmd().arg("-l").arg("--si").arg(file1).run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
assert!(result.stdout.contains(" 1.0k "));
|
||||
|
||||
scene
|
||||
.cmd("truncate")
|
||||
.arg("-s")
|
||||
.arg("+1000k")
|
||||
.arg(file)
|
||||
.arg(file1)
|
||||
.run();
|
||||
let result = scene.ucmd().arg("-hl").arg(file).run();
|
||||
|
||||
let result = scene.ucmd().arg("-hl").arg(file1).run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
assert!(result.stdout.contains("1.02M"));
|
||||
assert!(result.stdout.contains(" 1001K "));
|
||||
|
||||
let result = scene.ucmd().arg("-l").arg("--si").arg(file1).run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
assert!(result.stdout.contains(" 1.1M "));
|
||||
|
||||
let file2 = "test-human-2";
|
||||
let result = scene
|
||||
.cmd("truncate")
|
||||
.arg("-s")
|
||||
.arg("+12300k")
|
||||
.arg(file2)
|
||||
.run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
let result = scene.ucmd().arg("-hl").arg(file2).run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
// GNU rounds up, so we must too.
|
||||
assert!(result.stdout.contains(" 13M "));
|
||||
|
||||
let result = scene.ucmd().arg("-l").arg("--si").arg(file2).run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
// GNU rounds up, so we must too.
|
||||
assert!(result.stdout.contains(" 13M "));
|
||||
|
||||
let file3 = "test-human-3";
|
||||
let result = scene
|
||||
.cmd("truncate")
|
||||
.arg("-s")
|
||||
.arg("+9999")
|
||||
.arg(file3)
|
||||
.run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
|
||||
let result = scene.ucmd().arg("-hl").arg(file3).run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
assert!(result.stdout.contains(" 9.8K "));
|
||||
|
||||
let result = scene.ucmd().arg("-l").arg("--si").arg(file3).run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
assert!(result.success);
|
||||
assert!(result.stdout.contains(" 10k "));
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
|
@ -336,3 +869,81 @@ fn test_ls_hidden_windows() {
|
|||
assert!(result.success);
|
||||
assert!(result.stdout.contains(file));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ls_version_sort() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
for filename in &[
|
||||
"a2",
|
||||
"b1",
|
||||
"b20",
|
||||
"a1.4",
|
||||
"a1.40",
|
||||
"b3",
|
||||
"b11",
|
||||
"b20b",
|
||||
"b20a",
|
||||
"a100",
|
||||
"a1.13",
|
||||
"aa",
|
||||
"a1",
|
||||
"aaa",
|
||||
"a1.00000040",
|
||||
"abab",
|
||||
"ab",
|
||||
"a01.40",
|
||||
"a001.001",
|
||||
"a01.0000001",
|
||||
"a01.001",
|
||||
"a001.01",
|
||||
] {
|
||||
at.touch(filename);
|
||||
}
|
||||
|
||||
let mut expected = vec![
|
||||
"a1",
|
||||
"a001.001",
|
||||
"a001.01",
|
||||
"a01.0000001",
|
||||
"a01.001",
|
||||
"a1.4",
|
||||
"a1.13",
|
||||
"a01.40",
|
||||
"a1.00000040",
|
||||
"a1.40",
|
||||
"a2",
|
||||
"a100",
|
||||
"aa",
|
||||
"aaa",
|
||||
"ab",
|
||||
"abab",
|
||||
"b1",
|
||||
"b3",
|
||||
"b11",
|
||||
"b20",
|
||||
"b20a",
|
||||
"b20b",
|
||||
"", // because of '\n' at the end of the output
|
||||
];
|
||||
|
||||
let result = scene.ucmd().arg("-1v").run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
|
||||
assert_eq!(result.stdout.split('\n').collect::<Vec<_>>(), expected);
|
||||
|
||||
let result = scene.ucmd().arg("-1").arg("--sort=version").run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
|
||||
assert_eq!(result.stdout.split('\n').collect::<Vec<_>>(), expected);
|
||||
|
||||
let result = scene.ucmd().arg("-a1v").run();
|
||||
println!("stderr = {:?}", result.stderr);
|
||||
println!("stdout = {:?}", result.stdout);
|
||||
|
||||
expected.insert(0, "..");
|
||||
expected.insert(0, ".");
|
||||
assert_eq!(result.stdout.split('\n').collect::<Vec<_>>(), expected,)
|
||||
}
|
||||
|
|
|
@ -15,7 +15,9 @@ fn test_negative_adjustment() {
|
|||
// correctly.
|
||||
|
||||
let res = new_ucmd!().args(&["-n", "-1", "true"]).run();
|
||||
assert!(res.stderr.starts_with("nice: warning: setpriority: Permission denied"));
|
||||
assert!(res
|
||||
.stderr
|
||||
.starts_with("nice: warning: setpriority: Permission denied"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -23,8 +23,8 @@ fn test_padding_without_overflow() {
|
|||
.run()
|
||||
.stdout_is(
|
||||
"000001xL1\n001001xL2\n002001xL3\n003001xL4\n004001xL5\n005001xL6\n006001xL7\n0070\
|
||||
01xL8\n008001xL9\n009001xL10\n010001xL11\n011001xL12\n012001xL13\n013001xL14\n014\
|
||||
001xL15\n",
|
||||
01xL8\n008001xL9\n009001xL10\n010001xL11\n011001xL12\n012001xL13\n013001xL14\n014\
|
||||
001xL15\n",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ fn test_padding_with_overflow() {
|
|||
.run()
|
||||
.stdout_is(
|
||||
"0001xL1\n1001xL2\n2001xL3\n3001xL4\n4001xL5\n5001xL6\n6001xL7\n7001xL8\n8001xL9\n\
|
||||
9001xL10\n10001xL11\n11001xL12\n12001xL13\n13001xL14\n14001xL15\n",
|
||||
9001xL10\n10001xL11\n11001xL12\n12001xL13\n13001xL14\n14001xL15\n",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -45,15 +45,15 @@ fn test_sections_and_styles() {
|
|||
(
|
||||
"section.txt",
|
||||
"\nHEADER1\nHEADER2\n\n1 |BODY1\n2 \
|
||||
|BODY2\n\nFOOTER1\nFOOTER2\n\nNEXTHEADER1\nNEXTHEADER2\n\n1 \
|
||||
|NEXTBODY1\n2 |NEXTBODY2\n\nNEXTFOOTER1\nNEXTFOOTER2\n",
|
||||
|BODY2\n\nFOOTER1\nFOOTER2\n\nNEXTHEADER1\nNEXTHEADER2\n\n1 \
|
||||
|NEXTBODY1\n2 |NEXTBODY2\n\nNEXTFOOTER1\nNEXTFOOTER2\n",
|
||||
),
|
||||
(
|
||||
"joinblanklines.txt",
|
||||
"1 |Nonempty\n2 |Nonempty\n3 |Followed by 10x empty\n\n\n\n\n4 \
|
||||
|\n\n\n\n\n5 |\n6 |Followed by 5x empty\n\n\n\n\n7 |\n8 \
|
||||
|Followed by 4x empty\n\n\n\n\n9 |Nonempty\n10 |Nonempty\n11 \
|
||||
|Nonempty.\n",
|
||||
|\n\n\n\n\n5 |\n6 |Followed by 5x empty\n\n\n\n\n7 |\n8 \
|
||||
|Followed by 4x empty\n\n\n\n\n9 |Nonempty\n10 |Nonempty\n11 \
|
||||
|Nonempty.\n",
|
||||
),
|
||||
] {
|
||||
new_ucmd!()
|
||||
|
|
|
@ -1 +1,19 @@
|
|||
// ToDO: add tests
|
||||
use crate::common::util::*;
|
||||
use std::thread::sleep;
|
||||
|
||||
// General observation: nohup.out will not be created in tests run by cargo test
|
||||
// because stdin/stdout is not attached to a TTY.
|
||||
// All that can be tested is the side-effects.
|
||||
|
||||
#[test]
|
||||
#[cfg(any(target_os = "linux", target_os = "freebsd", target_vendor = "apple"))]
|
||||
fn test_nohup_multiple_args_and_flags() {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
|
||||
ucmd.args(&["touch", "-t", "1006161200", "file1", "file2"])
|
||||
.succeeds();
|
||||
sleep(std::time::Duration::from_millis(10));
|
||||
|
||||
assert!(at.file_exists("file1"));
|
||||
assert!(at.file_exists("file2"));
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ fn test_default_mode() {
|
|||
|
||||
// fail on long inputs
|
||||
new_ucmd!()
|
||||
.args(&[repeat_str("test", 20000)])
|
||||
.args(&["test".repeat(20000)])
|
||||
.fails()
|
||||
.no_stdout();
|
||||
}
|
||||
|
|
|
@ -177,7 +177,7 @@ fn test_rm_directory_without_flag() {
|
|||
let dir = "test_rm_directory_without_flag_dir";
|
||||
|
||||
at.mkdir(dir);
|
||||
|
||||
|
||||
let result = ucmd.arg(dir).fails();
|
||||
println!("{}", result.stderr);
|
||||
assert!(result
|
||||
|
|
|
@ -40,7 +40,7 @@ fn test_rmdir_nonempty_directory_no_parents() {
|
|||
|
||||
ucmd.arg(dir).fails().stderr_is(
|
||||
"rmdir: error: failed to remove 'test_rmdir_nonempty_no_parents': Directory not \
|
||||
empty\n",
|
||||
empty\n",
|
||||
);
|
||||
|
||||
assert!(at.dir_exists(dir));
|
||||
|
@ -60,9 +60,9 @@ fn test_rmdir_nonempty_directory_with_parents() {
|
|||
|
||||
ucmd.arg("-p").arg(dir).fails().stderr_is(
|
||||
"rmdir: error: failed to remove 'test_rmdir_nonempty/with/parents': Directory not \
|
||||
empty\nrmdir: error: failed to remove 'test_rmdir_nonempty/with': Directory not \
|
||||
empty\nrmdir: error: failed to remove 'test_rmdir_nonempty': Directory not \
|
||||
empty\n",
|
||||
empty\nrmdir: error: failed to remove 'test_rmdir_nonempty/with': Directory not \
|
||||
empty\nrmdir: error: failed to remove 'test_rmdir_nonempty': Directory not \
|
||||
empty\n",
|
||||
);
|
||||
|
||||
assert!(at.dir_exists(dir));
|
||||
|
|
|
@ -329,3 +329,17 @@ fn test_multiple_input_quiet_flag_overrides_verbose_flag_for_suppressing_headers
|
|||
.run()
|
||||
.stdout_is_fixture("foobar_multiple_quiet.expected");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_negative_indexing() {
|
||||
let positive_lines_index = new_ucmd!().arg("-n").arg("5").arg(FOOBAR_TXT).run();
|
||||
|
||||
let negative_lines_index = new_ucmd!().arg("-n").arg("-5").arg(FOOBAR_TXT).run();
|
||||
|
||||
let positive_bytes_index = new_ucmd!().arg("-c").arg("20").arg(FOOBAR_TXT).run();
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -15,3 +15,36 @@ fn test_sort_self_loop() {
|
|||
.succeeds()
|
||||
.stdout_only("first\nsecond\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_such_file() {
|
||||
let result = new_ucmd!().arg("invalid_file_txt").run();
|
||||
|
||||
assert_eq!(true, result.stderr.contains("No such file or directory"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
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);
|
||||
}
|
||||
|
||||
#[test]
|
||||
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);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiple_arguments() {
|
||||
let result = new_ucmd!()
|
||||
.arg("call_graph.txt")
|
||||
.arg("invalid_file.txt")
|
||||
.run();
|
||||
|
||||
assert_eq!(true, result.stderr.contains("error: Found argument 'invalid_file.txt' which wasn't expected, or isn't valid in this context"))
|
||||
}
|
||||
|
|
|
@ -136,3 +136,22 @@ fn unexpand_spaces_after_fields() {
|
|||
.run()
|
||||
.stdout_is("\t\tA B C D\t\t A\t\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unexpand_read_from_file() {
|
||||
new_ucmd!()
|
||||
.arg("with_spaces.txt")
|
||||
.arg("-t4")
|
||||
.run()
|
||||
.success();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unexpand_read_from_two_file() {
|
||||
new_ucmd!()
|
||||
.arg("with_spaces.txt")
|
||||
.arg("with_spaces.txt")
|
||||
.arg("-t4")
|
||||
.run()
|
||||
.success();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ fn test_unlink_multiple_files() {
|
|||
|
||||
ucmd.arg(file_a).arg(file_b).fails().stderr_is(
|
||||
"unlink: error: extra operand: 'test_unlink_multiple_file_b'\nTry 'unlink --help' \
|
||||
for more information.\n",
|
||||
for more information.\n",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ fn test_unlink_directory() {
|
|||
|
||||
ucmd.arg(dir).fails().stderr_is(
|
||||
"unlink: error: cannot unlink 'test_unlink_empty_directory': Not a regular file \
|
||||
or symlink\n",
|
||||
or symlink\n",
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,6 @@ fn test_unlink_nonexistent() {
|
|||
|
||||
new_ucmd!().arg(file).fails().stderr_is(
|
||||
"unlink: error: Cannot stat 'test_unlink_nonexistent': No such file or directory \
|
||||
(os error 2)\n",
|
||||
(os error 2)\n",
|
||||
);
|
||||
}
|
||||
|
|
|
@ -81,6 +81,6 @@ fn test_multiple_default() {
|
|||
.run()
|
||||
.stdout_is(
|
||||
" 13 109 772 lorem_ipsum.txt\n 18 204 1115 moby_dick.txt\n 5 57 302 \
|
||||
alice_in_wonderland.txt\n 36 370 2189 total\n",
|
||||
alice_in_wonderland.txt\n 36 370 2189 total\n",
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
/// Assertion helper macro for [`CmdResult`] types
|
||||
///
|
||||
/// [`CmdResult`]: crate::tests::common::util::CmdResult
|
||||
#[macro_export]
|
||||
macro_rules! assert_empty_stderr(
|
||||
($cond:expr) => (
|
||||
|
@ -7,6 +10,9 @@ macro_rules! assert_empty_stderr(
|
|||
);
|
||||
);
|
||||
|
||||
/// Assertion helper macro for [`CmdResult`] types
|
||||
///
|
||||
/// [`CmdResult`]: crate::tests::common::util::CmdResult
|
||||
#[macro_export]
|
||||
macro_rules! assert_empty_stdout(
|
||||
($cond:expr) => (
|
||||
|
@ -16,6 +22,9 @@ macro_rules! assert_empty_stdout(
|
|||
);
|
||||
);
|
||||
|
||||
/// Assertion helper macro for [`CmdResult`] types
|
||||
///
|
||||
/// [`CmdResult`]: crate::tests::common::util::CmdResult
|
||||
#[macro_export]
|
||||
macro_rules! assert_no_error(
|
||||
($cond:expr) => (
|
||||
|
@ -26,6 +35,7 @@ macro_rules! assert_no_error(
|
|||
);
|
||||
);
|
||||
|
||||
/// Platform-independent helper for constructing a PathBuf from individual elements
|
||||
#[macro_export]
|
||||
macro_rules! path_concat {
|
||||
($e:expr, ..$n:expr) => {{
|
||||
|
@ -47,6 +57,9 @@ macro_rules! path_concat {
|
|||
}};
|
||||
}
|
||||
|
||||
/// Deduce the name of the test binary from the test filename.
|
||||
///
|
||||
/// e.g.: `tests/by-util/test_cat.rs` -> `cat`
|
||||
#[macro_export]
|
||||
macro_rules! util_name {
|
||||
() => {
|
||||
|
@ -54,6 +67,16 @@ macro_rules! util_name {
|
|||
};
|
||||
}
|
||||
|
||||
/// Convenience macro for acquiring a [`UCommand`] builder.
|
||||
///
|
||||
/// Returns the following:
|
||||
/// - a [`UCommand`] builder for invoking the binary to be tested
|
||||
///
|
||||
/// This macro is intended for quick, single-call tests. For more complex tests
|
||||
/// that require multiple invocations of the tested binary, see [`TestScenario`]
|
||||
///
|
||||
/// [`UCommand`]: crate::tests::common::util::UCommand
|
||||
/// [`TestScenario]: crate::tests::common::util::TestScenario
|
||||
#[macro_export]
|
||||
macro_rules! new_ucmd {
|
||||
() => {
|
||||
|
@ -61,6 +84,18 @@ macro_rules! new_ucmd {
|
|||
};
|
||||
}
|
||||
|
||||
/// Convenience macro for acquiring a [`UCommand`] builder and a test path.
|
||||
///
|
||||
/// Returns a tuple containing the following:
|
||||
/// - an [`AsPath`] that points to a unique temporary test directory
|
||||
/// - a [`UCommand`] builder for invoking the binary to be tested
|
||||
///
|
||||
/// This macro is intended for quick, single-call tests. For more complex tests
|
||||
/// that require multiple invocations of the tested binary, see [`TestScenario`]
|
||||
///
|
||||
/// [`UCommand`]: crate::tests::common::util::UCommand
|
||||
/// [`AsPath`]: crate::tests::common::util::AsPath
|
||||
/// [`TestScenario]: crate::tests::common::util::TestScenario
|
||||
#[macro_export]
|
||||
macro_rules! at_and_ucmd {
|
||||
() => {{
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use std::env;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs::{self, File, OpenOptions};
|
||||
|
@ -27,7 +29,7 @@ static ALREADY_RUN: &str = " you have already run this UCommand, if you want to
|
|||
testing();";
|
||||
static MULTIPLE_STDIN_MEANINGLESS: &str = "Ucommand is designed around a typical use case of: provide args and input stream -> spawn process -> block until completion -> return output streams. For verifying that a particular section of the input stream is what causes a particular behavior, use the Command type directly.";
|
||||
|
||||
/// Test if the program are running under CI
|
||||
/// Test if the program is running under CI
|
||||
pub fn is_ci() -> bool {
|
||||
std::env::var("CI")
|
||||
.unwrap_or(String::from("false"))
|
||||
|
@ -55,14 +57,6 @@ fn read_scenario_fixture<S: AsRef<OsStr>>(tmpd: &Option<Rc<TempDir>>, file_rel_p
|
|||
AtPath::new(tmpdir_path).read(file_rel_path.as_ref().to_str().unwrap())
|
||||
}
|
||||
|
||||
pub fn repeat_str(s: &str, n: u32) -> String {
|
||||
let mut repeated = String::new();
|
||||
for _ in 0..n {
|
||||
repeated.push_str(s);
|
||||
}
|
||||
repeated
|
||||
}
|
||||
|
||||
/// A command result is the outputs of a command (streams and status code)
|
||||
/// within a struct which has convenience assertion functions about those outputs
|
||||
#[derive(Debug)]
|
||||
|
@ -384,8 +378,10 @@ impl AtPath {
|
|||
|
||||
/// An environment for running a single uutils test case, serves three functions:
|
||||
/// 1. centralizes logic for locating the uutils binary and calling the utility
|
||||
/// 2. provides a temporary directory for the test case
|
||||
/// 2. provides a unique temporary directory for the test case
|
||||
/// 3. copies over fixtures for the utility to the temporary directory
|
||||
///
|
||||
/// Fixtures can be found under `tests/fixtures/$util_name/`
|
||||
pub struct TestScenario {
|
||||
bin_path: PathBuf,
|
||||
util_name: String,
|
||||
|
@ -420,12 +416,16 @@ impl TestScenario {
|
|||
ts
|
||||
}
|
||||
|
||||
/// Returns builder for invoking the target uutils binary. Paths given are
|
||||
/// treated relative to the environment's unique temporary test directory.
|
||||
pub fn ucmd(&self) -> UCommand {
|
||||
let mut cmd = self.cmd(&self.bin_path);
|
||||
cmd.arg(&self.util_name);
|
||||
cmd
|
||||
}
|
||||
|
||||
/// Returns builder for invoking any system command. Paths given are treated
|
||||
/// relative to the environment's unique temporary test directory.
|
||||
pub fn cmd<S: AsRef<OsStr>>(&self, bin: S) -> UCommand {
|
||||
UCommand::new_from_tmp(bin, self.tmpd.clone(), true)
|
||||
}
|
||||
|
@ -495,6 +495,8 @@ impl UCommand {
|
|||
ucmd
|
||||
}
|
||||
|
||||
/// Add a parameter to the invocation. Path arguments are treated relative
|
||||
/// to the test environment directory.
|
||||
pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> Box<&mut UCommand> {
|
||||
if self.has_run {
|
||||
panic!(ALREADY_RUN);
|
||||
|
@ -505,6 +507,8 @@ impl UCommand {
|
|||
Box::new(self)
|
||||
}
|
||||
|
||||
/// Add multiple parameters to the invocation. Path arguments are treated relative
|
||||
/// to the test environment directory.
|
||||
pub fn args<S: AsRef<OsStr>>(&mut self, args: &[S]) -> Box<&mut UCommand> {
|
||||
if self.has_run {
|
||||
panic!(MULTIPLE_STDIN_MEANINGLESS);
|
||||
|
|
0
tests/fixtures/cp/dir_with_mount/copy_me.txt
vendored
Normal file
0
tests/fixtures/cp/dir_with_mount/copy_me.txt
vendored
Normal file
0
tests/fixtures/cp/dir_with_mount/copy_me/copy_me.txt
vendored
Normal file
0
tests/fixtures/cp/dir_with_mount/copy_me/copy_me.txt
vendored
Normal file
BIN
tests/fixtures/head/zero_terminated.expected
vendored
Normal file
BIN
tests/fixtures/head/zero_terminated.expected
vendored
Normal file
Binary file not shown.
BIN
tests/fixtures/head/zero_terminated.txt
vendored
Normal file
BIN
tests/fixtures/head/zero_terminated.txt
vendored
Normal file
Binary file not shown.
2
tests/fixtures/unexpand/with_spaces.txt
vendored
Normal file
2
tests/fixtures/unexpand/with_spaces.txt
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
abc d e f g \t\t A
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue