1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-08-01 13:37:48 +00:00

Merge branch 'master' of github.com:uutils/coreutils into refactoring_parse_size

This commit is contained in:
Jan Scheer 2021-06-03 21:13:44 +02:00
commit 130bf49e5d
112 changed files with 489 additions and 350 deletions

View file

@ -1,4 +1,4 @@
// spell-checker:ignore (flags) reflink (fs) tmpfs
// spell-checker:ignore (flags) reflink (fs) tmpfs (linux) rlimit Rlim NOFILE
use crate::common::util::*;
#[cfg(not(windows))]
@ -7,11 +7,15 @@ use std::fs::set_permissions;
#[cfg(not(windows))]
use std::os::unix::fs;
#[cfg(target_os = "linux")]
use std::os::unix::fs::PermissionsExt;
#[cfg(windows)]
use std::os::windows::fs::symlink_file;
#[cfg(target_os = "linux")]
use filetime::FileTime;
#[cfg(target_os = "linux")]
use rlimit::Resource;
#[cfg(not(windows))]
use std::env;
#[cfg(target_os = "linux")]
@ -1257,3 +1261,32 @@ fn test_cp_reflink_bad() {
.fails()
.stderr_contains("invalid argument");
}
#[test]
#[cfg(target_os = "linux")]
fn test_cp_reflink_insufficient_permission() {
let (at, mut ucmd) = at_and_ucmd!();
at.make_file("unreadable")
.set_permissions(PermissionsExt::from_mode(0o000))
.unwrap();
ucmd.arg("-r")
.arg("--reflink=auto")
.arg("unreadable")
.arg(TEST_EXISTING_FILE)
.fails()
.stderr_only("cp: 'unreadable' -> 'existing_file.txt': Permission denied (os error 13)");
}
#[cfg(target_os = "linux")]
#[test]
fn test_closes_file_descriptors() {
new_ucmd!()
.arg("-r")
.arg("--reflink=auto")
.arg("dir_with_10_files/")
.arg("dir_with_10_files_new/")
.with_limit(Resource::NOFILE, 9, 9)
.succeeds();
}

View file

@ -257,18 +257,37 @@ fn test_du_time() {
scene
.ccmd("touch")
.arg("-a")
.arg("-m")
.arg("-t")
.arg("201505150000")
.arg("date_test")
.succeeds();
scene
.ucmd()
.arg("--time")
.ccmd("touch")
.arg("-m")
.arg("-t")
.arg("201606160000")
.arg("date_test")
.succeeds()
.stdout_only("0\t2015-05-15 00:00\tdate_test\n");
.succeeds();
let result = scene.ucmd().arg("--time").arg("date_test").succeeds();
result.stdout_only("0\t2016-06-16 00:00\tdate_test\n");
let result = scene.ucmd().arg("--time=atime").arg("date_test").succeeds();
result.stdout_only("0\t2015-05-15 00:00\tdate_test\n");
let result = scene.ucmd().arg("--time=ctime").arg("date_test").succeeds();
result.stdout_only("0\t2016-06-16 00:00\tdate_test\n");
#[cfg(not(target_env = "musl"))]
{
use regex::Regex;
let re_birth =
Regex::new(r"0\t[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}\tdate_test").unwrap();
let result = scene.ucmd().arg("--time=birth").arg("date_test").succeeds();
result.stdout_matches(&re_birth);
}
}
#[cfg(not(target_os = "windows"))]

View file

@ -288,13 +288,14 @@ fn test_with_suppress_error_option() {
fn test_with_stdin() {
let expected_file_path = "stdin.log.expected";
let mut scenario = new_ucmd!();
let now = now_time();
scenario
.pipe_in_fixture("stdin.log")
.args(&["--pages=1:2", "-n", "-"])
.run()
.stdout_is_templated_fixture(
expected_file_path,
vec![(&"{last_modified_time}".to_string(), &now_time())],
vec![(&"{last_modified_time}".to_string(), &now)],
);
}
@ -381,22 +382,25 @@ fn test_with_mpr() {
let expected_test_file_path = "mpr.log.expected";
let expected_test_file_path1 = "mpr1.log.expected";
let expected_test_file_path2 = "mpr2.log.expected";
let now = now_time();
new_ucmd!()
.args(&["--pages=1:2", "-m", "-n", test_file_path, test_file_path1])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path,
vec![(&"{last_modified_time}".to_string(), &now_time())],
vec![(&"{last_modified_time}".to_string(), &now)],
);
let now = now_time();
new_ucmd!()
.args(&["--pages=2:4", "-m", "-n", test_file_path, test_file_path1])
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path1,
vec![(&"{last_modified_time}".to_string(), &now_time())],
vec![(&"{last_modified_time}".to_string(), &now)],
);
let now = now_time();
new_ucmd!()
.args(&[
"--pages=1:2",
@ -411,7 +415,7 @@ fn test_with_mpr() {
.succeeds()
.stdout_is_templated_fixture(
expected_test_file_path2,
vec![(&"{last_modified_time}".to_string(), &now_time())],
vec![(&"{last_modified_time}".to_string(), &now)],
);
}
@ -507,11 +511,12 @@ fn test_with_join_lines_option() {
let test_file_2 = "test.log";
let expected_file_path = "joined.log.expected";
let mut scenario = new_ucmd!();
let now = now_time();
scenario
.args(&["+1:2", "-J", "-m", test_file_1, test_file_2])
.run()
.stdout_is_templated_fixture(
expected_file_path,
vec![(&"{last_modified_time}".to_string(), &now_time())],
vec![(&"{last_modified_time}".to_string(), &now)],
);
}

View file

@ -1,5 +1,19 @@
use crate::common::util::*;
#[test]
fn test_rejects_nan() {
new_ucmd!().args(&["NaN"]).fails().stderr_only(
"seq: invalid 'not-a-number' argument: 'NaN'\nTry 'seq --help' for more information.",
);
}
#[test]
fn test_rejects_non_floats() {
new_ucmd!().args(&["foo"]).fails().stderr_only(
"seq: invalid floating point argument: 'foo'\nTry 'seq --help' for more information.",
);
}
// ---- Tests for the big integer based path ----
#[test]

View file

@ -163,6 +163,14 @@ fn test_multiple_decimals_numeric() {
)
}
#[test]
fn test_numeric_with_trailing_invalid_chars() {
test_helper(
"numeric_trailing_chars",
&["-n", "--numeric-sort", "--sort=numeric"],
)
}
#[test]
fn test_check_zero_terminated_failure() {
new_ucmd!()

View file

@ -289,15 +289,19 @@ fn test_filter_command_fails() {
#[test]
fn test_split_lines_number() {
// Test if stdout/stderr for '--lines' option is correct
new_ucmd!()
.args(&["--lines", "2"])
.pipe_in("abcde")
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.touch("file");
scene
.ucmd()
.args(&["--lines", "2", "file"])
.succeeds()
.no_stderr()
.no_stdout();
new_ucmd!()
.args(&["--lines", "2fb"])
.pipe_in("abcde")
scene
.ucmd()
.args(&["--lines", "2fb", "file"])
.fails()
.code_is(1)
.stderr_only("split: invalid number of lines: 2fb");

View file

@ -449,3 +449,20 @@ fn test_touch_mtime_dst_fails() {
ucmd.args(&["-m", "-t", &s, file]).fails();
}
}
#[test]
#[cfg(unix)]
fn test_touch_system_fails() {
let (_at, mut ucmd) = at_and_ucmd!();
let file = "/";
ucmd.args(&[file])
.fails()
.stderr_contains("setting times of '/'");
}
#[test]
fn test_touch_trailing_slash() {
let (_at, mut ucmd) = at_and_ucmd!();
let file = "no-file/";
ucmd.args(&[file]).fails();
}

View file

@ -50,14 +50,14 @@ 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
/// - an [`AtPath`] 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
/// [`AtPath`]: crate::tests::common::util::AtPath
/// [`TestScenario]: crate::tests::common::util::TestScenario
#[macro_export]
macro_rules! at_and_ucmd {

View file

@ -1,5 +1,10 @@
//spell-checker: ignore (linux) rlimit prlimit Rlim
#![allow(dead_code)]
use pretty_assertions::assert_eq;
#[cfg(target_os = "linux")]
use rlimit::{prlimit, rlim};
use std::env;
#[cfg(not(windows))]
use std::ffi::CString;
@ -724,6 +729,8 @@ pub struct UCommand {
stdout: Option<Stdio>,
stderr: Option<Stdio>,
bytes_into_stdin: Option<Vec<u8>>,
#[cfg(target_os = "linux")]
limits: Vec<(rlimit::Resource, rlim, rlim)>,
}
impl UCommand {
@ -758,6 +765,8 @@ impl UCommand {
stdin: None,
stdout: None,
stderr: None,
#[cfg(target_os = "linux")]
limits: vec![],
}
}
@ -855,6 +864,17 @@ impl UCommand {
self
}
#[cfg(target_os = "linux")]
pub fn with_limit(
&mut self,
resource: rlimit::Resource,
soft_limit: rlim,
hard_limit: rlim,
) -> &mut Self {
self.limits.push((resource, soft_limit, hard_limit));
self
}
/// Spawns the command, feeds the stdin if any, and returns the
/// child process immediately.
pub fn run_no_wait(&mut self) -> Child {
@ -871,6 +891,17 @@ impl UCommand {
.spawn()
.unwrap();
#[cfg(target_os = "linux")]
for &(resource, soft_limit, hard_limit) in &self.limits {
prlimit(
child.id() as i32,
resource,
Some((soft_limit, hard_limit)),
None,
)
.unwrap();
}
if let Some(ref input) = self.bytes_into_stdin {
let write_result = child
.stdin

0
tests/fixtures/cp/dir_with_10_files/0 vendored Normal file
View file

0
tests/fixtures/cp/dir_with_10_files/1 vendored Normal file
View file

0
tests/fixtures/cp/dir_with_10_files/2 vendored Normal file
View file

0
tests/fixtures/cp/dir_with_10_files/3 vendored Normal file
View file

0
tests/fixtures/cp/dir_with_10_files/4 vendored Normal file
View file

0
tests/fixtures/cp/dir_with_10_files/5 vendored Normal file
View file

0
tests/fixtures/cp/dir_with_10_files/6 vendored Normal file
View file

0
tests/fixtures/cp/dir_with_10_files/7 vendored Normal file
View file

0
tests/fixtures/cp/dir_with_10_files/8 vendored Normal file
View file

0
tests/fixtures/cp/dir_with_10_files/9 vendored Normal file
View file

View file

@ -1,3 +1,4 @@
K
844K
981K
11M

View file

@ -1,3 +1,6 @@
K
^ no match for key
_
844K
____
____

View file

@ -9,3 +9,4 @@
844K
981K
13M
K

View file

@ -0,0 +1,5 @@
-.05,
-x
0.abc
0foo
100

View file

@ -0,0 +1,15 @@
-.05,
____
_____
-x
^ no match for key
__
0.abc
__
_____
0foo
_
____
100
___
____

View file

@ -0,0 +1,5 @@
0foo
0.abc
100
-.05,
-x