Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion tests/test_uudoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub const TESTS_BINARY: &str = env!("CARGO_BIN_EXE_uudoc");
fn init() {
// No need for unsafe here
unsafe {
std::env::set_var("UUTESTS_BINARY_PATH", TESTS_BINARY);
env::set_var("UUTESTS_BINARY_PATH", TESTS_BINARY);
}
// Print for debugging
eprintln!("Setting UUTESTS_BINARY_PATH={TESTS_BINARY}");
Expand Down
3 changes: 3 additions & 0 deletions tests/uutests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ version.workspace = true
[package.metadata.docs.rs]
all-features = true

[lints]
workspace = true

[lib]
path = "src/lib/lib.rs"

Expand Down
89 changes: 50 additions & 39 deletions tests/uutests/src/lib/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ const DEFAULT_ENV: [(&str, &str); 2] = [("LC_ALL", "C"), ("TZ", "UTC")];

/// Test if the program is running under CI
pub fn is_ci() -> bool {
std::env::var("CI").is_ok_and(|s| s.eq_ignore_ascii_case("true"))
env::var("CI").is_ok_and(|s| s.eq_ignore_ascii_case("true"))
}

/// Read a test scenario fixture, returning its bytes
Expand Down Expand Up @@ -942,7 +942,7 @@ pub fn get_root_path() -> &'static str {
///
/// `true` if both paths have the same set of extended attributes, `false` otherwise.
#[cfg(all(unix, not(any(target_os = "macos", target_os = "openbsd"))))]
pub fn compare_xattrs<P: AsRef<std::path::Path>>(path1: P, path2: P) -> bool {
pub fn compare_xattrs<P: AsRef<Path>>(path1: P, path2: P) -> bool {
let get_sorted_xattrs = |path: P| {
xattr::list(path)
.map(|attrs| {
Expand Down Expand Up @@ -1031,13 +1031,13 @@ impl AtPath {

pub fn write(&self, name: &str, contents: &str) {
log_info("write(default)", self.plus_as_string(name));
std::fs::write(self.plus(name), contents)
fs::write(self.plus(name), contents)
.unwrap_or_else(|e| panic!("Couldn't write {name}: {e}"));
}

pub fn write_bytes(&self, name: &str, contents: &[u8]) {
log_info("write(default)", self.plus_as_string(name));
std::fs::write(self.plus(name), contents)
fs::write(self.plus(name), contents)
.unwrap_or_else(|e| panic!("Couldn't write {name}: {e}"));
}

Expand Down Expand Up @@ -1079,23 +1079,37 @@ impl AtPath {
pub fn rename(&self, source: &str, target: &str) {
let source = self.plus(source);
let target = self.plus(target);
log_info("rename", format!("{source:?} {target:?}"));
std::fs::rename(&source, &target)
.unwrap_or_else(|e| panic!("Couldn't rename {source:?} -> {target:?}: {e}"));
log_info(
"rename",
format!("{} {}", source.display(), target.display()),
);
fs::rename(&source, &target).unwrap_or_else(|e| {
panic!(
"Couldn't rename {} -> {}: {e}",
source.display(),
target.display()
)
});
}

pub fn remove(&self, source: &str) {
let source = self.plus(source);
log_info("remove", format!("{source:?}"));
std::fs::remove_file(&source).unwrap_or_else(|e| panic!("Couldn't remove {source:?}: {e}"));
log_info("remove", format!("{}", source.display()));
remove_file(&source)
.unwrap_or_else(|e| panic!("Couldn't remove {}: {e}", source.display()));
}

pub fn copy(&self, source: &str, target: &str) {
let source = self.plus(source);
let target = self.plus(target);
log_info("copy", format!("{source:?} {target:?}"));
std::fs::copy(&source, &target)
.unwrap_or_else(|e| panic!("Couldn't copy {source:?} -> {target:?}: {e}"));
log_info("copy", format!("{} {}", source.display(), target.display()));
fs::copy(&source, &target).unwrap_or_else(|e| {
panic!(
"Couldn't copy {} -> {}: {e}",
source.display(),
target.display()
)
});
}

pub fn rmdir(&self, dir: &str) {
Expand Down Expand Up @@ -1308,9 +1322,9 @@ impl AtPath {
#[cfg(not(windows))]
pub fn set_mode(&self, filename: &str, mode: u32) {
let path = self.plus(filename);
let mut perms = std::fs::metadata(&path).unwrap().permissions();
let mut perms = fs::metadata(&path).unwrap().permissions();
perms.set_mode(mode);
std::fs::set_permissions(&path, perms).unwrap();
fs::set_permissions(&path, perms).unwrap();
}
}

Expand Down Expand Up @@ -1691,11 +1705,11 @@ impl UCommand {
}

#[cfg(unix)]
fn read_from_pty(pty_fd: std::os::fd::OwnedFd, out: File) {
let read_file = std::fs::File::from(pty_fd);
let mut reader = std::io::BufReader::new(read_file);
let mut writer = std::io::BufWriter::new(out);
let result = std::io::copy(&mut reader, &mut writer);
fn read_from_pty(pty_fd: OwnedFd, out: File) {
let read_file = File::from(pty_fd);
let mut reader = io::BufReader::new(read_file);
let mut writer = BufWriter::new(out);
let result = io::copy(&mut reader, &mut writer);
match result {
Ok(_) => {}
// Input/output error (os error 5) is returned due to pipe closes. Buffer gets content anyway.
Expand All @@ -1716,7 +1730,7 @@ impl UCommand {
if let Some(mut captured_output_i) = captured_output {
let fd = captured_output_i.try_clone().unwrap();

let handle = std::thread::Builder::new()
let handle = thread::Builder::new()
.name(name)
.spawn(move || {
Self::read_from_pty(pty_fd_master, fd);
Expand Down Expand Up @@ -1788,7 +1802,7 @@ impl UCommand {
{
self.args.push_front(c_arg);
}
};
}

// unwrap is safe here because we have set `self.bin_path` before
let mut command = Command::new(self.bin_path.as_ref().unwrap());
Expand Down Expand Up @@ -1875,7 +1889,7 @@ impl UCommand {
.stdin(self.stdin.take().unwrap_or_else(Stdio::null))
.stdout(stdout)
.stderr(stderr);
};
}

#[cfg(unix)]
if let Some(simulated_terminal) = &self.terminal_simulation {
Expand Down Expand Up @@ -2050,7 +2064,7 @@ impl std::fmt::Display for UCommand {
struct CapturedOutput {
current_file: File,
output: tempfile::NamedTempFile, // drop last
reader_thread_handle: Option<thread::JoinHandle<()>>,
reader_thread_handle: Option<JoinHandle<()>>,
}

impl CapturedOutput {
Expand All @@ -2064,7 +2078,7 @@ impl CapturedOutput {
}

/// Try to clone the file pointer.
fn try_clone(&mut self) -> io::Result<File> {
fn try_clone(&mut self) -> Result<File> {
self.output.as_file().try_clone()
}

Expand Down Expand Up @@ -2265,7 +2279,7 @@ pub struct UChild {
stdin_pty: Option<File>,
ignore_stdin_write_error: bool,
stderr_to_stdout: bool,
join_handle: Option<JoinHandle<io::Result<()>>>,
join_handle: Option<JoinHandle<Result<()>>>,
timeout: Option<Duration>,
tmpd: Option<Rc<TempDir>>, // drop last
}
Expand Down Expand Up @@ -2341,7 +2355,7 @@ impl UChild {
///
/// If [`Child::kill`] returned an error or if the child process could not be terminated within
/// `self.timeout` or the default of 60s.
pub fn try_kill(&mut self) -> io::Result<()> {
pub fn try_kill(&mut self) -> Result<()> {
let start = Instant::now();
self.raw.kill()?;

Expand Down Expand Up @@ -2402,10 +2416,7 @@ impl UChild {
/// If [`Child::kill`] returned an error or if the child process could not be terminated within
/// `self.timeout` or the default of 60s.
#[cfg(unix)]
pub fn try_kill_with_custom_signal(
&mut self,
signal_name: sys::signal::Signal,
) -> io::Result<()> {
pub fn try_kill_with_custom_signal(&mut self, signal_name: sys::signal::Signal) -> Result<()> {
let start = Instant::now();
sys::signal::kill(
nix::unistd::Pid::from_raw(self.raw.id().try_into().unwrap()),
Expand Down Expand Up @@ -2462,7 +2473,7 @@ impl UChild {
/// # Errors
///
/// Returns the error from the call to `wait_with_output` if any
pub fn wait(self) -> io::Result<CmdResult> {
pub fn wait(self) -> Result<CmdResult> {
let (bin_path, util_name, tmpd) = (
self.bin_path.clone(),
self.util_name.clone(),
Expand Down Expand Up @@ -2491,7 +2502,7 @@ impl UChild {
///
/// If `self.timeout` is reached while waiting or [`Child::wait_with_output`] returned an
/// error.
fn wait_with_output(mut self) -> io::Result<Output> {
fn wait_with_output(mut self) -> Result<Output> {
// some apps do not stop execution until their stdin gets closed.
// to prevent a endless waiting here, we close the stdin.
self.join(); // ensure that all pending async input is piped in
Expand Down Expand Up @@ -2533,7 +2544,7 @@ impl UChild {
.join()
.expect("Error joining with the piping stdin thread")
.unwrap();
};
}

if let Some(stdout) = self.captured_stdout.as_mut() {
if let Some(handle) = stdout.reader_thread_handle.take() {
Expand Down Expand Up @@ -2754,7 +2765,7 @@ impl UChild {
}
let mut writer = self.take_stdin_as_writer();

let join_handle = std::thread::Builder::new()
let join_handle = thread::Builder::new()
.name("pipe_in".to_string())
.spawn(
move || match writer.write_all(&content).and_then(|()| writer.flush()) {
Expand Down Expand Up @@ -2797,7 +2808,7 @@ impl UChild {
///
/// # Errors
/// If [`std::process::ChildStdin::write_all`] or [`std::process::ChildStdin::flush`] returned an error
pub fn try_write_in<T: Into<Vec<u8>>>(&mut self, data: T) -> io::Result<()> {
pub fn try_write_in<T: Into<Vec<u8>>>(&mut self, data: T) -> Result<()> {
let ignore_stdin_write_error = self.ignore_stdin_write_error;
let mut writer = self.access_stdin_as_writer();

Expand Down Expand Up @@ -2867,8 +2878,8 @@ pub fn whoami() -> String {

// Use environment variable to get current user instead of
// invoking `whoami` and fall back to user "nobody" on error.
std::env::var("USER")
.or_else(|_| std::env::var("USERNAME"))
env::var("USER")
.or_else(|_| env::var("USERNAME"))
.unwrap_or_else(|e| {
println!("{UUTILS_WARNING}: {e}, using \"nobody\" instead");
"nobody".to_string()
Expand Down Expand Up @@ -3182,7 +3193,7 @@ mod tests {
#[ctor::ctor]
fn init() {
unsafe {
std::env::set_var("UUTESTS_BINARY_PATH", "");
env::set_var("UUTESTS_BINARY_PATH", "");
}
}

Expand Down Expand Up @@ -3429,7 +3440,7 @@ mod tests {
match check_coreutil_version("id", VERSION_MIN) {
Ok(s) => assert!(s.starts_with("uutils-tests-")),
Err(s) => assert!(s.starts_with("uutils-tests-warning")),
};
}
#[cfg(target_os = "linux")]
std::assert_eq!(
check_coreutil_version("no test name", VERSION_MIN),
Expand Down
Loading