mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-29 20:17:45 +00:00
Merge branch 'master' into implement-more
This commit is contained in:
commit
482e340e11
74 changed files with 43638 additions and 1359 deletions
|
@ -98,7 +98,7 @@ fn test_wrap_bad_arg() {
|
|||
.arg(wrap_param)
|
||||
.arg("b")
|
||||
.fails()
|
||||
.stderr_only("base32: error: invalid wrap size: ‘b’: invalid digit found in string\n");
|
||||
.stderr_only("base32: error: Invalid wrap size: ‘b’: invalid digit found in string\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,21 @@ fn test_encode() {
|
|||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_only("aGVsbG8sIHdvcmxkIQ==\n");
|
||||
|
||||
// Using '-' as our file
|
||||
new_ucmd!()
|
||||
.arg("-")
|
||||
.pipe_in(input)
|
||||
.succeeds()
|
||||
.stdout_only("aGVsbG8sIHdvcmxkIQ==\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_base64_encode_file() {
|
||||
new_ucmd!()
|
||||
.arg("input-simple.txt")
|
||||
.succeeds()
|
||||
.stdout_only("SGVsbG8sIFdvcmxkIQo=\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -60,10 +75,9 @@ fn test_wrap() {
|
|||
#[test]
|
||||
fn test_wrap_no_arg() {
|
||||
for wrap_param in vec!["-w", "--wrap"] {
|
||||
new_ucmd!().arg(wrap_param).fails().stderr_only(format!(
|
||||
"base64: error: Argument to option '{}' missing\n",
|
||||
if wrap_param == "-w" { "w" } else { "wrap" }
|
||||
));
|
||||
new_ucmd!().arg(wrap_param).fails().stderr_contains(
|
||||
&"The argument '--wrap <wrap>' requires a value but none was supplied",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,6 +88,24 @@ fn test_wrap_bad_arg() {
|
|||
.arg(wrap_param)
|
||||
.arg("b")
|
||||
.fails()
|
||||
.stderr_only("base64: error: invalid wrap size: ‘b’: invalid digit found in string\n");
|
||||
.stderr_only("base64: error: Invalid wrap size: ‘b’: invalid digit found in string\n");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_base64_extra_operand() {
|
||||
// Expect a failure when multiple files are specified.
|
||||
new_ucmd!()
|
||||
.arg("a.txt")
|
||||
.arg("a.txt")
|
||||
.fails()
|
||||
.stderr_only("base64: error: extra operand ‘a.txt’");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_base64_file_not_found() {
|
||||
new_ucmd!()
|
||||
.arg("a.txt")
|
||||
.fails()
|
||||
.stderr_only("base64: error: a.txt: No such file or directory");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,29 @@
|
|||
use crate::common::util::*;
|
||||
use std::ffi::OsStr;
|
||||
|
||||
#[test]
|
||||
fn test_help() {
|
||||
for help_flg in vec!["-h", "--help"] {
|
||||
new_ucmd!()
|
||||
.arg(&help_flg)
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
.stdout_contains("USAGE:");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_version() {
|
||||
for version_flg in vec!["-V", "--version"] {
|
||||
assert!(new_ucmd!()
|
||||
.arg(&version_flg)
|
||||
.succeeds()
|
||||
.no_stderr()
|
||||
.stdout_str()
|
||||
.starts_with("basename"));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_directory() {
|
||||
new_ucmd!()
|
||||
|
@ -81,11 +104,25 @@ fn test_no_args() {
|
|||
expect_error(vec![]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_args_output() {
|
||||
new_ucmd!()
|
||||
.fails()
|
||||
.stderr_is("basename: error: missing operand\nTry 'basename --help' for more information.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_too_many_args() {
|
||||
expect_error(vec!["a", "b", "c"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_too_many_args_output() {
|
||||
new_ucmd!().args(&["a", "b", "c"]).fails().stderr_is(
|
||||
"basename: error: extra operand 'c'\nTry 'basename --help' for more information.",
|
||||
);
|
||||
}
|
||||
|
||||
fn test_invalid_utf8_args(os_str: &OsStr) {
|
||||
let test_vec = vec![os_str.to_os_string()];
|
||||
new_ucmd!().args(&test_vec).succeeds().stdout_is("fo<EFBFBD>o\n");
|
||||
|
|
|
@ -20,4 +20,16 @@ fn test_df_compatible_si() {
|
|||
new_ucmd!().arg("-aH").succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_df_output() {
|
||||
if cfg!(target_os = "macos") {
|
||||
new_ucmd!().arg("-H").arg("-total").succeeds().
|
||||
stdout_only("Filesystem Size Used Available Capacity Use% Mounted on \n");
|
||||
} else {
|
||||
new_ucmd!().arg("-H").arg("-total").succeeds().stdout_only(
|
||||
"Filesystem Size Used Available Use% Mounted on \n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ToDO: more tests...
|
||||
|
|
|
@ -16,6 +16,21 @@ fn test_path_without_trailing_slashes() {
|
|||
.stdout_is("/root/alpha/beta/gamma/delta/epsilon\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_path_without_trailing_slashes_and_zero() {
|
||||
new_ucmd!()
|
||||
.arg("-z")
|
||||
.arg("/root/alpha/beta/gamma/delta/epsilon/omega")
|
||||
.succeeds()
|
||||
.stdout_is("/root/alpha/beta/gamma/delta/epsilon\u{0}");
|
||||
|
||||
new_ucmd!()
|
||||
.arg("--zero")
|
||||
.arg("/root/alpha/beta/gamma/delta/epsilon/omega")
|
||||
.succeeds()
|
||||
.stdout_is("/root/alpha/beta/gamma/delta/epsilon\u{0}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_root() {
|
||||
new_ucmd!().arg("/").run().stdout_is("/\n");
|
||||
|
|
|
@ -1 +1,126 @@
|
|||
// ToDO: add tests
|
||||
use crate::common::util::*;
|
||||
use regex::Regex;
|
||||
use std::os::unix::process::ExitStatusExt;
|
||||
use std::process::{Child, Command};
|
||||
|
||||
// A child process the tests will try to kill.
|
||||
struct Target {
|
||||
child: Child,
|
||||
killed: bool,
|
||||
}
|
||||
|
||||
impl Target {
|
||||
// Creates a target that will naturally die after some time if not killed
|
||||
// fast enough.
|
||||
// This timeout avoids hanging failing tests.
|
||||
fn new() -> Target {
|
||||
Target {
|
||||
child: Command::new("sleep")
|
||||
.arg("30")
|
||||
.spawn()
|
||||
.expect("cannot spawn target"),
|
||||
killed: false,
|
||||
}
|
||||
}
|
||||
|
||||
// Waits for the target to complete and returns the signal it received if any.
|
||||
fn wait_for_signal(&mut self) -> Option<i32> {
|
||||
let sig = self.child.wait().expect("cannot wait on target").signal();
|
||||
self.killed = true;
|
||||
sig
|
||||
}
|
||||
|
||||
fn pid(&self) -> u32 {
|
||||
self.child.id()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Target {
|
||||
// Terminates this target to avoid littering test boxes with zombi processes
|
||||
// when a test fails after creating a target but before killing it.
|
||||
fn drop(&mut self) {
|
||||
if !self.killed {
|
||||
self.child.kill().expect("cannot kill target");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kill_list_all_signals() {
|
||||
// Check for a few signals. Do not try to be comprehensive.
|
||||
new_ucmd!()
|
||||
.arg("-l")
|
||||
.succeeds()
|
||||
.stdout_contains("KILL")
|
||||
.stdout_contains("TERM")
|
||||
.stdout_contains("HUP");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kill_list_all_signals_as_table() {
|
||||
// Check for a few signals. Do not try to be comprehensive.
|
||||
new_ucmd!()
|
||||
.arg("-t")
|
||||
.succeeds()
|
||||
.stdout_contains("KILL")
|
||||
.stdout_contains("TERM")
|
||||
.stdout_contains("HUP");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kill_list_one_signal_from_name() {
|
||||
// Use SIGKILL because it is 9 on all unixes.
|
||||
new_ucmd!()
|
||||
.arg("-l")
|
||||
.arg("KILL")
|
||||
.succeeds()
|
||||
.stdout_matches(&Regex::new("\\b9\\b").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kill_set_bad_signal_name() {
|
||||
new_ucmd!()
|
||||
.arg("-s")
|
||||
.arg("IAMNOTASIGNAL")
|
||||
.fails()
|
||||
.stderr_contains("unknown signal");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kill_with_default_signal() {
|
||||
let mut target = Target::new();
|
||||
new_ucmd!().arg(format!("{}", target.pid())).succeeds();
|
||||
assert_eq!(target.wait_for_signal(), Some(libc::SIGTERM));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kill_with_signal_number_old_form() {
|
||||
let mut target = Target::new();
|
||||
new_ucmd!()
|
||||
.arg("-9")
|
||||
.arg(format!("{}", target.pid()))
|
||||
.succeeds();
|
||||
assert_eq!(target.wait_for_signal(), Some(9));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kill_with_signal_number_new_form() {
|
||||
let mut target = Target::new();
|
||||
new_ucmd!()
|
||||
.arg("-s")
|
||||
.arg("9")
|
||||
.arg(format!("{}", target.pid()))
|
||||
.succeeds();
|
||||
assert_eq!(target.wait_for_signal(), Some(9));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kill_with_signal_name_new_form() {
|
||||
let mut target = Target::new();
|
||||
new_ucmd!()
|
||||
.arg("-s")
|
||||
.arg("KILL")
|
||||
.arg(format!("{}", target.pid()))
|
||||
.succeeds();
|
||||
assert_eq!(target.wait_for_signal(), Some(libc::SIGKILL));
|
||||
}
|
||||
|
|
|
@ -39,3 +39,25 @@ fn test_link_nonexistent_file() {
|
|||
assert!(!at.file_exists(file));
|
||||
assert!(!at.file_exists(link));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_link_one_argument() {
|
||||
let (_, mut ucmd) = at_and_ucmd!();
|
||||
let file = "test_link_argument";
|
||||
ucmd.args(&[file]).fails().stderr_contains(
|
||||
"error: The argument '<FILES>...' requires at least 2 values, but only 1 was provide",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_link_three_arguments() {
|
||||
let (_, mut ucmd) = at_and_ucmd!();
|
||||
let arguments = vec![
|
||||
"test_link_argument1",
|
||||
"test_link_argument2",
|
||||
"test_link_argument3",
|
||||
];
|
||||
ucmd.args(&arguments[..]).fails().stderr_contains(
|
||||
format!("error: The value '{}' was provided to '<FILES>...', but it wasn't expecting any more values", arguments[2]),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -43,23 +43,74 @@ fn test_ls_a() {
|
|||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.touch(".test-1");
|
||||
at.mkdir("some-dir");
|
||||
at.touch(
|
||||
Path::new("some-dir")
|
||||
.join(".test-2")
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
let result = scene.ucmd().succeeds();
|
||||
let stdout = result.stdout_str();
|
||||
assert!(!stdout.contains(".test-1"));
|
||||
assert!(!stdout.contains(".."));
|
||||
let re_pwd = Regex::new(r"^\.\n").unwrap();
|
||||
|
||||
// Using the present working directory
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-1")
|
||||
.succeeds()
|
||||
.stdout_does_not_contain(".test-1")
|
||||
.stdout_does_not_contain("..")
|
||||
.stdout_does_not_match(&re_pwd);
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-a")
|
||||
.arg("-1")
|
||||
.succeeds()
|
||||
.stdout_contains(&".test-1")
|
||||
.stdout_contains(&"..");
|
||||
.stdout_contains(&"..")
|
||||
.stdout_matches(&re_pwd);
|
||||
|
||||
let result = scene.ucmd().arg("-A").succeeds();
|
||||
result.stdout_contains(".test-1");
|
||||
let stdout = result.stdout_str();
|
||||
assert!(!stdout.contains(".."));
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-A")
|
||||
.arg("-1")
|
||||
.succeeds()
|
||||
.stdout_contains(".test-1")
|
||||
.stdout_does_not_contain("..")
|
||||
.stdout_does_not_match(&re_pwd);
|
||||
|
||||
// Using a subdirectory
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-1")
|
||||
.arg("some-dir")
|
||||
.succeeds()
|
||||
.stdout_does_not_contain(".test-2")
|
||||
.stdout_does_not_contain("..")
|
||||
.stdout_does_not_match(&re_pwd);
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-a")
|
||||
.arg("-1")
|
||||
.arg("some-dir")
|
||||
.succeeds()
|
||||
.stdout_contains(&".test-2")
|
||||
.stdout_contains(&"..")
|
||||
.no_stderr()
|
||||
.stdout_matches(&re_pwd);
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-A")
|
||||
.arg("-1")
|
||||
.arg("some-dir")
|
||||
.succeeds()
|
||||
.stdout_contains(".test-2")
|
||||
.stdout_does_not_contain("..")
|
||||
.stdout_does_not_match(&re_pwd);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -482,7 +533,6 @@ fn test_ls_sort_name() {
|
|||
.succeeds()
|
||||
.stdout_is(["test-1", "test-2", "test-3\n"].join(sep));
|
||||
|
||||
// Order of a named sort ignores leading dots.
|
||||
let scene_dot = TestScenario::new(util_name!());
|
||||
let at = &scene_dot.fixtures;
|
||||
at.touch(".a");
|
||||
|
@ -495,7 +545,7 @@ fn test_ls_sort_name() {
|
|||
.arg("--sort=name")
|
||||
.arg("-A")
|
||||
.succeeds()
|
||||
.stdout_is([".a", "a", ".b", "b\n"].join(sep));
|
||||
.stdout_is([".a", ".b", "a", "b\n"].join(sep));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -558,6 +608,113 @@ fn test_ls_long_ctime() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_ls_order_birthtime() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
|
||||
/*
|
||||
Here we make 2 files with a timeout in between.
|
||||
After creating the first file try to sync it.
|
||||
This ensures the file gets created immediately instead of being saved
|
||||
inside the OS's IO operation buffer.
|
||||
Without this, both files might accidentally be created at the same time.
|
||||
*/
|
||||
at.make_file("test-birthtime-1").sync_all().unwrap();
|
||||
at.make_file("test-birthtime-2").sync_all().unwrap();
|
||||
at.open("test-birthtime-1");
|
||||
|
||||
let result = scene.ucmd().arg("--time=birth").arg("-t").run();
|
||||
|
||||
#[cfg(not(windows))]
|
||||
assert_eq!(result.stdout_str(), "test-birthtime-2\ntest-birthtime-1\n");
|
||||
#[cfg(windows)]
|
||||
assert_eq!(result.stdout_str(), "test-birthtime-2 test-birthtime-1\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ls_styles() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
let at = &scene.fixtures;
|
||||
at.touch("test");
|
||||
|
||||
let re_full = Regex::new(
|
||||
r"[a-z-]* \d* \w* \w* \d* \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d* \+\d{4} test\n",
|
||||
)
|
||||
.unwrap();
|
||||
let re_long =
|
||||
Regex::new(r"[a-z-]* \d* \w* \w* \d* \d{4}-\d{2}-\d{2} \d{2}:\d{2} test\n").unwrap();
|
||||
let re_iso = Regex::new(r"[a-z-]* \d* \w* \w* \d* \d{2}-\d{2} \d{2}:\d{2} test\n").unwrap();
|
||||
let re_locale =
|
||||
Regex::new(r"[a-z-]* \d* \w* \w* \d* [A-Z][a-z]{2} ( |\d)\d \d{2}:\d{2} test\n").unwrap();
|
||||
|
||||
//full-iso
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg("-l")
|
||||
.arg("--time-style=full-iso")
|
||||
.succeeds();
|
||||
assert!(re_full.is_match(&result.stdout_str()));
|
||||
//long-iso
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg("-l")
|
||||
.arg("--time-style=long-iso")
|
||||
.succeeds();
|
||||
assert!(re_long.is_match(&result.stdout_str()));
|
||||
//iso
|
||||
let result = scene.ucmd().arg("-l").arg("--time-style=iso").succeeds();
|
||||
assert!(re_iso.is_match(&result.stdout_str()));
|
||||
//locale
|
||||
let result = scene.ucmd().arg("-l").arg("--time-style=locale").succeeds();
|
||||
assert!(re_locale.is_match(&result.stdout_str()));
|
||||
|
||||
//Overwrite options tests
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg("-l")
|
||||
.arg("--time-style=long-iso")
|
||||
.arg("--time-style=iso")
|
||||
.succeeds();
|
||||
assert!(re_iso.is_match(&result.stdout_str()));
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg("--time-style=iso")
|
||||
.arg("--full-time")
|
||||
.succeeds();
|
||||
assert!(re_full.is_match(&result.stdout_str()));
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg("--full-time")
|
||||
.arg("--time-style=iso")
|
||||
.succeeds();
|
||||
assert!(re_iso.is_match(&result.stdout_str()));
|
||||
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg("--full-time")
|
||||
.arg("--time-style=iso")
|
||||
.arg("--full-time")
|
||||
.succeeds();
|
||||
assert!(re_full.is_match(&result.stdout_str()));
|
||||
|
||||
let result = scene
|
||||
.ucmd()
|
||||
.arg("--full-time")
|
||||
.arg("-x")
|
||||
.arg("-l")
|
||||
.succeeds();
|
||||
assert!(re_full.is_match(&result.stdout_str()));
|
||||
|
||||
at.touch("test2");
|
||||
let result = scene.ucmd().arg("--full-time").arg("-x").succeeds();
|
||||
#[cfg(not(windows))]
|
||||
assert_eq!(result.stdout_str(), "test\ntest2\n");
|
||||
#[cfg(windows)]
|
||||
assert_eq!(result.stdout_str(), "test test2\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ls_order_time() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
|
|
|
@ -34,6 +34,36 @@ fn test_long_format() {
|
|||
));
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_long_format_multiple_users() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
|
||||
let expected = scene
|
||||
.cmd_keepenv(util_name!())
|
||||
.env("LANGUAGE", "C")
|
||||
.arg("-l")
|
||||
.arg("root")
|
||||
.arg("root")
|
||||
.arg("root")
|
||||
.succeeds();
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-l")
|
||||
.arg("root")
|
||||
.arg("root")
|
||||
.arg("root")
|
||||
.succeeds()
|
||||
.stdout_is(expected.stdout_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_long_format_wo_user() {
|
||||
// "no username specified; at least one must be specified when using -l"
|
||||
new_ucmd!().arg("-l").fails().code_is(1);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_short_format_i() {
|
||||
|
|
|
@ -103,7 +103,7 @@ fn test_relpath_with_from_with_d() {
|
|||
at.mkdir_all(from);
|
||||
|
||||
// d is part of subpath -> expect relative path
|
||||
let mut result_stdout = scene
|
||||
let mut _result_stdout = scene
|
||||
.ucmd()
|
||||
.arg(to)
|
||||
.arg(from)
|
||||
|
@ -112,17 +112,17 @@ fn test_relpath_with_from_with_d() {
|
|||
.stdout_move_str();
|
||||
// relax rules for windows test environment
|
||||
#[cfg(not(windows))]
|
||||
assert!(Path::new(&result_stdout).is_relative());
|
||||
assert!(Path::new(&_result_stdout).is_relative());
|
||||
|
||||
// d is not part of subpath -> expect absolut path
|
||||
result_stdout = scene
|
||||
_result_stdout = scene
|
||||
.ucmd()
|
||||
.arg(to)
|
||||
.arg(from)
|
||||
.arg("-dnon_existing")
|
||||
.succeeds()
|
||||
.stdout_move_str();
|
||||
assert!(Path::new(&result_stdout).is_absolute());
|
||||
assert!(Path::new(&_result_stdout).is_absolute());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,12 +135,12 @@ fn test_relpath_no_from_no_d() {
|
|||
let to: &str = &convert_path(test.to);
|
||||
at.mkdir_all(to);
|
||||
|
||||
let result_stdout = scene.ucmd().arg(to).succeeds().stdout_move_str();
|
||||
let _result_stdout = scene.ucmd().arg(to).succeeds().stdout_move_str();
|
||||
#[cfg(not(windows))]
|
||||
assert_eq!(result_stdout, format!("{}\n", to));
|
||||
assert_eq!(_result_stdout, format!("{}\n", to));
|
||||
// relax rules for windows test environment
|
||||
#[cfg(windows)]
|
||||
assert!(result_stdout.ends_with(&format!("{}\n", to)));
|
||||
assert!(_result_stdout.ends_with(&format!("{}\n", to)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,31 @@ fn test_helper(file_name: &str, args: &str) {
|
|||
.stdout_is_fixture(format!("{}.expected.debug", file_name));
|
||||
}
|
||||
|
||||
// FYI, the initialization size of our Line struct is 96 bytes.
|
||||
//
|
||||
// At very small buffer sizes, with that overhead we are certainly going
|
||||
// to overrun our buffer way, way, way too quickly because of these excess
|
||||
// bytes for the struct.
|
||||
//
|
||||
// For instance, seq 0..20000 > ...text = 108894 bytes
|
||||
// But overhead is 1920000 + 108894 = 2028894 bytes
|
||||
//
|
||||
// Or kjvbible-random.txt = 4332506 bytes, but minimum size of its
|
||||
// 99817 lines in memory * 96 bytes = 9582432 bytes
|
||||
//
|
||||
// Here, we test 108894 bytes with a 50K buffer
|
||||
//
|
||||
#[test]
|
||||
fn test_larger_than_specified_segment() {
|
||||
new_ucmd!()
|
||||
.arg("-n")
|
||||
.arg("-S")
|
||||
.arg("50K")
|
||||
.arg("ext_sort.txt")
|
||||
.succeeds()
|
||||
.stdout_is_fixture(format!("{}", "ext_sort.expected"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_months_whitespace() {
|
||||
test_helper("months-whitespace", "-M");
|
||||
|
@ -34,6 +59,18 @@ fn test_human_numeric_whitespace() {
|
|||
test_helper("human-numeric-whitespace", "-h");
|
||||
}
|
||||
|
||||
// This tests where serde often fails when reading back JSON
|
||||
// if it finds a null value
|
||||
#[test]
|
||||
fn test_extsort_as64_bailout() {
|
||||
new_ucmd!()
|
||||
.arg("-g")
|
||||
.arg("-S 5K")
|
||||
.arg("multiple_decimals_general.txt")
|
||||
.succeeds()
|
||||
.stdout_is_fixture("multiple_decimals_general.expected");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiple_decimals_general() {
|
||||
test_helper("multiple_decimals_general", "-g")
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// This file is part of the uutils coreutils package.
|
||||
//
|
||||
// (c) mahkoh (ju.orth [at] gmail [dot] com)
|
||||
// (c) Daniel Rocco <drocco@gmail.com>
|
||||
//
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
@ -9,11 +10,466 @@
|
|||
|
||||
use crate::common::util::*;
|
||||
|
||||
#[test]
|
||||
fn test_empty_test_equivalent_to_false() {
|
||||
new_ucmd!().run().status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_string_is_false() {
|
||||
new_ucmd!().arg("").run().status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solo_not() {
|
||||
new_ucmd!().arg("!").succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solo_and_or_or_is_a_literal() {
|
||||
// /bin/test '' -a '' => 1; so test(1) must interpret `-a` by itself as
|
||||
// a literal string
|
||||
new_ucmd!().arg("-a").succeeds();
|
||||
new_ucmd!().arg("-o").succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_double_not_is_false() {
|
||||
new_ucmd!().args(&["!", "!"]).run().status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_and_not_is_false() {
|
||||
new_ucmd!().args(&["-a", "!"]).run().status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_and_is_false() {
|
||||
// `-a` is a literal here & has nonzero length
|
||||
new_ucmd!().args(&["!", "-a"]).run().status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_and_not_succeeds() {
|
||||
new_ucmd!().args(&["!", "-a", "!"]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_simple_or() {
|
||||
new_ucmd!().args(&["foo", "-o", ""]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_negated_or() {
|
||||
new_ucmd!()
|
||||
.args(&["!", "foo", "-o", "bar"])
|
||||
.run()
|
||||
.status_code(1);
|
||||
new_ucmd!().args(&["foo", "-o", "!", "bar"]).succeeds();
|
||||
new_ucmd!()
|
||||
.args(&["!", "foo", "-o", "!", "bar"])
|
||||
.run()
|
||||
.status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strlen_of_nothing() {
|
||||
// odd but matches GNU, which must interpret -n as a literal here
|
||||
new_ucmd!().arg("-n").succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_strlen_of_empty() {
|
||||
new_ucmd!().args(&["-n", ""]).run().status_code(1);
|
||||
|
||||
// STRING equivalent to -n STRING
|
||||
new_ucmd!().arg("").run().status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nothing_is_empty() {
|
||||
// -z is a literal here and has nonzero length
|
||||
new_ucmd!().arg("-z").succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero_len_of_empty() {
|
||||
new_ucmd!().args(&["-z", ""]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solo_paren_is_literal() {
|
||||
let scenario = TestScenario::new(util_name!());
|
||||
let tests = [["("], [")"]];
|
||||
|
||||
for test in &tests {
|
||||
scenario.ucmd().args(&test[..]).succeeds();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solo_empty_parenthetical_is_error() {
|
||||
new_ucmd!().args(&["(", ")"]).run().status_code(2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero_len_equals_zero_len() {
|
||||
new_ucmd!().args(&["", "=", ""]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_zero_len_not_equals_zero_len_is_false() {
|
||||
new_ucmd!().args(&["", "!=", ""]).run().status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_string_comparison() {
|
||||
let scenario = TestScenario::new(util_name!());
|
||||
let tests = [
|
||||
["foo", "!=", "bar"],
|
||||
["contained\nnewline", "=", "contained\nnewline"],
|
||||
["(", "=", "("],
|
||||
["(", "!=", ")"],
|
||||
["!", "=", "!"],
|
||||
];
|
||||
|
||||
for test in &tests {
|
||||
scenario.ucmd().args(&test[..]).succeeds();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "fixme: error reporting"]
|
||||
fn test_dangling_string_comparison_is_error() {
|
||||
new_ucmd!()
|
||||
.args(&["missing_something", "="])
|
||||
.run()
|
||||
.status_code(2)
|
||||
.stderr_is("test: missing argument after ‘=’");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_stringop_is_literal_after_bang() {
|
||||
let scenario = TestScenario::new(util_name!());
|
||||
let tests = [
|
||||
["!", "="],
|
||||
["!", "!="],
|
||||
["!", "-eq"],
|
||||
["!", "-ne"],
|
||||
["!", "-lt"],
|
||||
["!", "-le"],
|
||||
["!", "-gt"],
|
||||
["!", "-ge"],
|
||||
["!", "-ef"],
|
||||
["!", "-nt"],
|
||||
["!", "-ot"],
|
||||
];
|
||||
|
||||
for test in &tests {
|
||||
scenario.ucmd().args(&test[..]).run().status_code(1);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_a_bunch_of_not() {
|
||||
new_ucmd!()
|
||||
.args(&["!", "", "!=", "", "-a", "!", "", "!=", ""])
|
||||
.succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pseudofloat_equal() {
|
||||
new_ucmd!().args(&["123.45", "=", "123.45"]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pseudofloat_not_equal() {
|
||||
new_ucmd!().args(&["123.45", "!=", "123.450"]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_negative_arg_is_a_string() {
|
||||
new_ucmd!().arg("-12345").succeeds();
|
||||
new_ucmd!().arg("--qwert").succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_some_int_compares() {
|
||||
let scenario = TestScenario::new(util_name!());
|
||||
|
||||
let tests = [
|
||||
["0", "-eq", "0"],
|
||||
["0", "-ne", "1"],
|
||||
["421", "-lt", "3720"],
|
||||
["0", "-le", "0"],
|
||||
["11", "-gt", "10"],
|
||||
["1024", "-ge", "512"],
|
||||
["9223372036854775806", "-le", "9223372036854775807"],
|
||||
];
|
||||
|
||||
for test in &tests {
|
||||
scenario.ucmd().args(&test[..]).succeeds();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "fixme: evaluation error (code 1); GNU returns 0"]
|
||||
fn test_values_greater_than_i64_allowed() {
|
||||
new_ucmd!()
|
||||
.args(&["9223372036854775808", "-gt", "0"])
|
||||
.succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_negative_int_compare() {
|
||||
let scenario = TestScenario::new(util_name!());
|
||||
|
||||
let tests = [
|
||||
["-1", "-eq", "-1"],
|
||||
["-1", "-ne", "-2"],
|
||||
["-3720", "-lt", "-421"],
|
||||
["-10", "-le", "-10"],
|
||||
["-21", "-gt", "-22"],
|
||||
["-128", "-ge", "-256"],
|
||||
["-9223372036854775808", "-le", "-9223372036854775807"],
|
||||
];
|
||||
|
||||
for test in &tests {
|
||||
scenario.ucmd().args(&test[..]).succeeds();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_float_inequality_is_error() {
|
||||
new_ucmd!()
|
||||
.args(&["123.45", "-ge", "6"])
|
||||
.run()
|
||||
.status_code(2)
|
||||
.stderr_is("test: invalid integer ‘123.45’");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(windows))]
|
||||
fn test_invalid_utf8_integer_compare() {
|
||||
use std::ffi::OsStr;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
|
||||
let source = [0x66, 0x6f, 0x80, 0x6f];
|
||||
let arg = OsStr::from_bytes(&source[..]);
|
||||
|
||||
let mut cmd = new_ucmd!();
|
||||
cmd.arg("123").arg("-ne");
|
||||
cmd.raw.arg(arg);
|
||||
|
||||
cmd.run()
|
||||
.status_code(2)
|
||||
.stderr_is("test: invalid integer ‘fo<66>o’");
|
||||
|
||||
let mut cmd = new_ucmd!();
|
||||
cmd.raw.arg(arg);
|
||||
cmd.arg("-eq").arg("456");
|
||||
|
||||
cmd.run()
|
||||
.status_code(2)
|
||||
.stderr_is("test: invalid integer ‘fo<66>o’");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "fixme: parse/evaluation error (code 2); GNU returns 1"]
|
||||
fn test_file_is_itself() {
|
||||
new_ucmd!()
|
||||
.args(&["regular_file", "-ef", "regular_file"])
|
||||
.succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "fixme: parse/evaluation error (code 2); GNU returns 1"]
|
||||
fn test_file_is_newer_than_and_older_than_itself() {
|
||||
// odd but matches GNU
|
||||
new_ucmd!()
|
||||
.args(&["regular_file", "-nt", "regular_file"])
|
||||
.run()
|
||||
.status_code(1);
|
||||
new_ucmd!()
|
||||
.args(&["regular_file", "-ot", "regular_file"])
|
||||
.run()
|
||||
.status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "todo: implement these"]
|
||||
fn test_newer_file() {
|
||||
let scenario = TestScenario::new(util_name!());
|
||||
|
||||
scenario.cmd("touch").arg("newer_file").succeeds();
|
||||
scenario
|
||||
.cmd("touch")
|
||||
.args(&["-m", "-d", "last Thursday", "regular_file"])
|
||||
.succeeds();
|
||||
|
||||
scenario
|
||||
.ucmd()
|
||||
.args(&["newer_file", "-nt", "regular_file"])
|
||||
.succeeds();
|
||||
scenario
|
||||
.ucmd()
|
||||
.args(&["regular_file", "-ot", "newer_file"])
|
||||
.succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_file_exists() {
|
||||
new_ucmd!().args(&["-e", "regular_file"]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nonexistent_file_does_not_exist() {
|
||||
new_ucmd!()
|
||||
.args(&["-e", "nonexistent_file"])
|
||||
.run()
|
||||
.status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nonexistent_file_is_not_regular() {
|
||||
new_ucmd!()
|
||||
.args(&["-f", "nonexistent_file"])
|
||||
.run()
|
||||
.status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_file_exists_and_is_regular() {
|
||||
new_ucmd!().args(&["-f", "regular_file"]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(windows))] // FIXME: implement on Windows
|
||||
fn test_file_is_readable() {
|
||||
new_ucmd!().args(&["-r", "regular_file"]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(windows))] // FIXME: implement on Windows
|
||||
fn test_file_is_not_readable() {
|
||||
let scenario = TestScenario::new(util_name!());
|
||||
let mut ucmd = scenario.ucmd();
|
||||
let mut chmod = scenario.cmd("chmod");
|
||||
|
||||
scenario.fixtures.touch("crypto_file");
|
||||
chmod.args(&["u-r", "crypto_file"]).succeeds();
|
||||
|
||||
ucmd.args(&["!", "-r", "crypto_file"]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(windows))] // FIXME: implement on Windows
|
||||
fn test_file_is_writable() {
|
||||
new_ucmd!().args(&["-w", "regular_file"]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(windows))] // FIXME: implement on Windows
|
||||
fn test_file_is_not_writable() {
|
||||
let scenario = TestScenario::new(util_name!());
|
||||
let mut ucmd = scenario.ucmd();
|
||||
let mut chmod = scenario.cmd("chmod");
|
||||
|
||||
scenario.fixtures.touch("immutable_file");
|
||||
chmod.args(&["u-w", "immutable_file"]).succeeds();
|
||||
|
||||
ucmd.args(&["!", "-w", "immutable_file"]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_file_is_not_executable() {
|
||||
new_ucmd!().args(&["!", "-x", "regular_file"]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(windows))] // FIXME: implement on Windows
|
||||
fn test_file_is_executable() {
|
||||
let scenario = TestScenario::new(util_name!());
|
||||
let mut chmod = scenario.cmd("chmod");
|
||||
|
||||
chmod.args(&["u+x", "regular_file"]).succeeds();
|
||||
|
||||
scenario.ucmd().args(&["-x", "regular_file"]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_not_empty() {
|
||||
new_ucmd!().args(&["-s", "non_empty_file"]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nonexistent_file_size_test_is_false() {
|
||||
new_ucmd!()
|
||||
.args(&["-s", "nonexistent_file"])
|
||||
.run()
|
||||
.status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_not_is_not_empty() {
|
||||
new_ucmd!().args(&["!", "-s", "regular_file"]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(not(windows))]
|
||||
fn test_symlink_is_symlink() {
|
||||
let scenario = TestScenario::new(util_name!());
|
||||
let mut ln = scenario.cmd("ln");
|
||||
|
||||
// creating symlinks requires admin on Windows
|
||||
ln.args(&["-s", "regular_file", "symlink"]).succeeds();
|
||||
|
||||
// FIXME: implement on Windows
|
||||
scenario.ucmd().args(&["-h", "symlink"]).succeeds();
|
||||
scenario.ucmd().args(&["-L", "symlink"]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_file_is_not_symlink() {
|
||||
let scenario = TestScenario::new(util_name!());
|
||||
|
||||
scenario
|
||||
.ucmd()
|
||||
.args(&["!", "-h", "regular_file"])
|
||||
.succeeds();
|
||||
scenario
|
||||
.ucmd()
|
||||
.args(&["!", "-L", "regular_file"])
|
||||
.succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nonexistent_file_is_not_symlink() {
|
||||
let scenario = TestScenario::new(util_name!());
|
||||
|
||||
scenario
|
||||
.ucmd()
|
||||
.args(&["!", "-h", "nonexistent_file"])
|
||||
.succeeds();
|
||||
scenario
|
||||
.ucmd()
|
||||
.args(&["!", "-L", "nonexistent_file"])
|
||||
.succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_op_prec_and_or_1() {
|
||||
new_ucmd!().args(&[" ", "-o", "", "-a", ""]).succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_op_prec_and_or_1_overridden_by_parentheses() {
|
||||
new_ucmd!()
|
||||
.args(&["(", " ", "-o", "", ")", "-a", ""])
|
||||
.run()
|
||||
.status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_op_prec_and_or_2() {
|
||||
new_ucmd!()
|
||||
|
@ -22,6 +478,54 @@ fn test_op_prec_and_or_2() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_or_as_filename() {
|
||||
new_ucmd!().args(&["x", "-a", "-z", "-o"]).fails();
|
||||
fn test_op_prec_and_or_2_overridden_by_parentheses() {
|
||||
new_ucmd!()
|
||||
.args(&["", "-a", "(", "", "-o", " ", ")", "-a", " "])
|
||||
.run()
|
||||
.status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "fixme: error reporting"]
|
||||
fn test_dangling_parenthesis() {
|
||||
new_ucmd!()
|
||||
.args(&["(", "(", "a", "!=", "b", ")", "-o", "-n", "c"])
|
||||
.run()
|
||||
.status_code(2);
|
||||
new_ucmd!()
|
||||
.args(&["(", "(", "a", "!=", "b", ")", "-o", "-n", "c", ")"])
|
||||
.succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_complicated_parenthesized_expression() {
|
||||
new_ucmd!()
|
||||
.args(&[
|
||||
"(", "(", "!", "(", "a", "=", "b", ")", "-o", "c", "=", "d", ")", "-a", "(", "q", "!=",
|
||||
"r", ")", ")",
|
||||
])
|
||||
.succeeds();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_erroneous_parenthesized_expression() {
|
||||
new_ucmd!()
|
||||
.args(&["a", "!=", "(", "b", "-a", "b", ")", "!=", "c"])
|
||||
.run()
|
||||
.status_code(2)
|
||||
.stderr_is("test: extra argument ‘b’");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_or_as_filename() {
|
||||
new_ucmd!()
|
||||
.args(&["x", "-a", "-z", "-o"])
|
||||
.run()
|
||||
.status_code(1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "GNU considers this an error"]
|
||||
fn test_strlen_and_nothing() {
|
||||
new_ucmd!().args(&["-n", "a", "-a"]).run().status_code(2);
|
||||
}
|
||||
|
|
|
@ -45,6 +45,70 @@ fn test_delete_complement() {
|
|||
.stdout_is("ac");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_complement_2() {
|
||||
new_ucmd!()
|
||||
.args(&["-d", "-C", "0-9"])
|
||||
.pipe_in("Phone: 01234 567890")
|
||||
.succeeds()
|
||||
.stdout_is("01234567890");
|
||||
new_ucmd!()
|
||||
.args(&["-d", "--complement", "0-9"])
|
||||
.pipe_in("Phone: 01234 567890")
|
||||
.succeeds()
|
||||
.stdout_is("01234567890");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_complement1() {
|
||||
new_ucmd!()
|
||||
.args(&["-c", "a", "X"])
|
||||
.pipe_in("ab")
|
||||
.run()
|
||||
.stdout_is("aX");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_complement2() {
|
||||
new_ucmd!()
|
||||
.args(&["-c", "0-9", "x"])
|
||||
.pipe_in("Phone: 01234 567890")
|
||||
.run()
|
||||
.stdout_is("xxxxxxx01234x567890");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_complement3() {
|
||||
new_ucmd!()
|
||||
.args(&["-c", "abcdefgh", "123"])
|
||||
.pipe_in("the cat and the bat")
|
||||
.run()
|
||||
.stdout_is("3he3ca33a3d33he3ba3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_complement4() {
|
||||
// $ echo -n '0x1y2z3' | tr -c '0-@' '*-~'
|
||||
// 0~1~2~3
|
||||
new_ucmd!()
|
||||
.args(&["-c", "0-@", "*-~"])
|
||||
.pipe_in("0x1y2z3")
|
||||
.run()
|
||||
.stdout_is("0~1~2~3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "fixme: GNU tr returns '0a1b2c3' instead of '0~1~2~3', see #2158"]
|
||||
fn test_complement5() {
|
||||
// $ echo '0x1y2z3' | tr -c '\0-@' '*-~'
|
||||
// 0a1b2c3
|
||||
new_ucmd!()
|
||||
.args(&["-c", "\\0-@", "*-~"])
|
||||
.pipe_in("0x1y2z3")
|
||||
.run()
|
||||
.stdout_is("0a1b2c3");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_squeeze() {
|
||||
new_ucmd!()
|
||||
|
@ -63,6 +127,24 @@ fn test_squeeze_complement() {
|
|||
.stdout_is("aaBcDcc");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_translate_and_squeeze() {
|
||||
new_ucmd!()
|
||||
.args(&["-s", "x", "y"])
|
||||
.pipe_in("xx")
|
||||
.run()
|
||||
.stdout_is("y");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_translate_and_squeeze_multiple_lines() {
|
||||
new_ucmd!()
|
||||
.args(&["-s", "x", "y"])
|
||||
.pipe_in("xxaax\nxaaxx")
|
||||
.run()
|
||||
.stdout_is("yaay\nyaay");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete_and_squeeze() {
|
||||
new_ucmd!()
|
||||
|
|
|
@ -224,8 +224,14 @@ fn test_size_and_reference() {
|
|||
let mut file1 = at.make_file(TFILE1);
|
||||
let mut file2 = at.make_file(TFILE2);
|
||||
file1.write_all(b"1234567890").unwrap();
|
||||
ucmd.args(&["--reference", TFILE1, "--size", "+5", TFILE2]).succeeds();
|
||||
ucmd.args(&["--reference", TFILE1, "--size", "+5", TFILE2])
|
||||
.succeeds();
|
||||
file2.seek(SeekFrom::End(0)).unwrap();
|
||||
let actual = file2.seek(SeekFrom::Current(0)).unwrap();
|
||||
assert!(expected == actual, "expected '{}' got '{}'", expected, actual);
|
||||
assert!(
|
||||
expected == actual,
|
||||
"expected '{}' got '{}'",
|
||||
expected,
|
||||
actual
|
||||
);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,12 @@ fn test_uname_kernel_version() {
|
|||
fn test_uname_kernel() {
|
||||
let (_, mut ucmd) = at_and_ucmd!();
|
||||
|
||||
let result = ucmd.arg("-o").succeeds();
|
||||
#[cfg(target_os = "linux")]
|
||||
assert!(result.stdout_str().to_lowercase().contains("linux"));
|
||||
{
|
||||
let result = ucmd.arg("-o").succeeds();
|
||||
assert!(result.stdout_str().to_lowercase().contains("linux"));
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
let result = ucmd.arg("-o").succeeds();
|
||||
}
|
||||
|
|
|
@ -112,3 +112,60 @@ fn test_multiple_default() {
|
|||
alice_in_wonderland.txt\n 36 370 2189 total\n",
|
||||
);
|
||||
}
|
||||
|
||||
/// Test for an empty file.
|
||||
#[test]
|
||||
fn test_file_empty() {
|
||||
// TODO There is a leading space in the output that should be
|
||||
// removed; see issue #2173.
|
||||
new_ucmd!()
|
||||
.args(&["-clmwL", "emptyfile.txt"])
|
||||
.run()
|
||||
.stdout_is(" 0 0 0 0 0 emptyfile.txt\n");
|
||||
}
|
||||
|
||||
/// Test for an file containing a single non-whitespace character
|
||||
/// *without* a trailing newline.
|
||||
#[test]
|
||||
fn test_file_single_line_no_trailing_newline() {
|
||||
// TODO There is a leading space in the output that should be
|
||||
// removed; see issue #2173.
|
||||
new_ucmd!()
|
||||
.args(&["-clmwL", "notrailingnewline.txt"])
|
||||
.run()
|
||||
.stdout_is(" 1 1 2 2 1 notrailingnewline.txt\n");
|
||||
}
|
||||
|
||||
/// Test for a file that has 100 empty lines (that is, the contents of
|
||||
/// the file are the newline character repeated one hundred times).
|
||||
#[test]
|
||||
fn test_file_many_empty_lines() {
|
||||
// TODO There is a leading space in the output that should be
|
||||
// removed; see issue #2173.
|
||||
new_ucmd!()
|
||||
.args(&["-clmwL", "manyemptylines.txt"])
|
||||
.run()
|
||||
.stdout_is(" 100 0 100 100 0 manyemptylines.txt\n");
|
||||
}
|
||||
|
||||
/// Test for a file that has one long line comprising only spaces.
|
||||
#[test]
|
||||
fn test_file_one_long_line_only_spaces() {
|
||||
// TODO There is a leading space in the output that should be
|
||||
// removed; see issue #2173.
|
||||
new_ucmd!()
|
||||
.args(&["-clmwL", "onelongemptyline.txt"])
|
||||
.run()
|
||||
.stdout_is(" 1 0 10001 10001 10000 onelongemptyline.txt\n");
|
||||
}
|
||||
|
||||
/// Test for a file that has one long line comprising a single "word".
|
||||
#[test]
|
||||
fn test_file_one_long_word() {
|
||||
// TODO There is a leading space in the output that should be
|
||||
// removed; see issue #2173.
|
||||
new_ucmd!()
|
||||
.args(&["-clmwL", "onelongword.txt"])
|
||||
.run()
|
||||
.stdout_is(" 1 1 10001 10001 10000 onelongword.txt\n");
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
#[cfg(target_os = "linux")]
|
||||
use crate::common::util::*;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_count() {
|
||||
for opt in vec!["-q", "--count"] {
|
||||
new_ucmd!().arg(opt).run().stdout_is(expected_result(opt));
|
||||
new_ucmd!()
|
||||
.arg(opt)
|
||||
.succeeds()
|
||||
.stdout_is(expected_result(opt));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,17 +15,21 @@ fn test_count() {
|
|||
#[test]
|
||||
fn test_boot() {
|
||||
for opt in vec!["-b", "--boot"] {
|
||||
new_ucmd!().arg(opt).run().stdout_is(expected_result(opt));
|
||||
new_ucmd!()
|
||||
.arg(opt)
|
||||
.succeeds()
|
||||
.stdout_is(expected_result(opt));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_heading() {
|
||||
for opt in vec!["-H"] {
|
||||
for opt in vec!["-H", "--heading"] {
|
||||
// allow whitespace variation
|
||||
// * minor whitespace differences occur between platform built-in outputs; specifically number of TABs between "TIME" and "COMMENT" may be variant
|
||||
let actual = new_ucmd!().arg(opt).run().stdout_move_str();
|
||||
// * minor whitespace differences occur between platform built-in outputs;
|
||||
// specifically number of TABs between "TIME" and "COMMENT" may be variant
|
||||
let actual = new_ucmd!().arg(opt).succeeds().stdout_move_str();
|
||||
let expect = expected_result(opt);
|
||||
println!("actual: {:?}", actual);
|
||||
println!("expect: {:?}", expect);
|
||||
|
@ -37,7 +43,10 @@ fn test_heading() {
|
|||
#[test]
|
||||
fn test_short() {
|
||||
for opt in vec!["-s", "--short"] {
|
||||
new_ucmd!().arg(opt).run().stdout_is(expected_result(opt));
|
||||
new_ucmd!()
|
||||
.arg(opt)
|
||||
.succeeds()
|
||||
.stdout_is(expected_result(opt));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,7 +54,10 @@ fn test_short() {
|
|||
#[test]
|
||||
fn test_login() {
|
||||
for opt in vec!["-l", "--login"] {
|
||||
new_ucmd!().arg(opt).run().stdout_is(expected_result(opt));
|
||||
new_ucmd!()
|
||||
.arg(opt)
|
||||
.succeeds()
|
||||
.stdout_is(expected_result(opt));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +65,109 @@ fn test_login() {
|
|||
#[test]
|
||||
fn test_m() {
|
||||
for opt in vec!["-m"] {
|
||||
new_ucmd!().arg(opt).run().stdout_is(expected_result(opt));
|
||||
new_ucmd!()
|
||||
.arg(opt)
|
||||
.succeeds()
|
||||
.stdout_is(expected_result(opt));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_process() {
|
||||
for opt in vec!["-p", "--process"] {
|
||||
new_ucmd!()
|
||||
.arg(opt)
|
||||
.succeeds()
|
||||
.stdout_is(expected_result(opt));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_runlevel() {
|
||||
for opt in vec!["-r", "--runlevel"] {
|
||||
new_ucmd!()
|
||||
.arg(opt)
|
||||
.succeeds()
|
||||
.stdout_is(expected_result(opt));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_time() {
|
||||
for opt in vec!["-t", "--time"] {
|
||||
new_ucmd!()
|
||||
.arg(opt)
|
||||
.succeeds()
|
||||
.stdout_is(expected_result(opt));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_mesg() {
|
||||
for opt in vec!["-w", "-T", "--users", "--message", "--writable"] {
|
||||
new_ucmd!()
|
||||
.arg(opt)
|
||||
.succeeds()
|
||||
.stdout_is(expected_result(opt));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_arg1_arg2() {
|
||||
let scene = TestScenario::new(util_name!());
|
||||
|
||||
let expected = scene
|
||||
.cmd_keepenv(util_name!())
|
||||
.env("LANGUAGE", "C")
|
||||
.arg("am")
|
||||
.arg("i")
|
||||
.succeeds();
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("am")
|
||||
.arg("i")
|
||||
.succeeds()
|
||||
.stdout_is(expected.stdout_str());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_too_many_args() {
|
||||
let expected =
|
||||
"error: The value 'u' was provided to '<FILE>...', but it wasn't expecting any more values";
|
||||
|
||||
new_ucmd!()
|
||||
.arg("am")
|
||||
.arg("i")
|
||||
.arg("u")
|
||||
.fails()
|
||||
.stderr_contains(expected);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_users() {
|
||||
for opt in vec!["-u", "--users"] {
|
||||
new_ucmd!()
|
||||
.arg(opt)
|
||||
.succeeds()
|
||||
.stdout_is(expected_result(opt));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_lookup() {
|
||||
for opt in vec!["--lookup"] {
|
||||
new_ucmd!()
|
||||
.arg(opt)
|
||||
.succeeds()
|
||||
.stdout_is(expected_result(opt));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,15 +175,60 @@ fn test_m() {
|
|||
#[test]
|
||||
fn test_dead() {
|
||||
for opt in vec!["-d", "--dead"] {
|
||||
new_ucmd!().arg(opt).run().stdout_is(expected_result(opt));
|
||||
new_ucmd!()
|
||||
.arg(opt)
|
||||
.succeeds()
|
||||
.stdout_is(expected_result(opt));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_all_separately() {
|
||||
// -a, --all same as -b -d --login -p -r -t -T -u
|
||||
let scene = TestScenario::new(util_name!());
|
||||
|
||||
let expected = scene
|
||||
.cmd_keepenv(util_name!())
|
||||
.env("LANGUAGE", "C")
|
||||
.arg("-b")
|
||||
.arg("-d")
|
||||
.arg("--login")
|
||||
.arg("-p")
|
||||
.arg("-r")
|
||||
.arg("-t")
|
||||
.arg("-T")
|
||||
.arg("-u")
|
||||
.succeeds();
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("-b")
|
||||
.arg("-d")
|
||||
.arg("--login")
|
||||
.arg("-p")
|
||||
.arg("-r")
|
||||
.arg("-t")
|
||||
.arg("-T")
|
||||
.arg("-u")
|
||||
.succeeds()
|
||||
.stdout_is(expected.stdout_str());
|
||||
|
||||
scene
|
||||
.ucmd()
|
||||
.arg("--all")
|
||||
.succeeds()
|
||||
.stdout_is(expected.stdout_str());
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
#[test]
|
||||
fn test_all() {
|
||||
for opt in vec!["-a", "--all"] {
|
||||
new_ucmd!().arg(opt).run().stdout_is(expected_result(opt));
|
||||
new_ucmd!()
|
||||
.arg(opt)
|
||||
.succeeds()
|
||||
.stdout_is(expected_result(opt));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,6 +238,6 @@ fn expected_result(arg: &str) -> String {
|
|||
.cmd_keepenv(util_name!())
|
||||
.env("LANGUAGE", "C")
|
||||
.args(&[arg])
|
||||
.run()
|
||||
.succeeds()
|
||||
.stdout_move_str()
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue