From db26dabd6eb803694fe51a55d7690cbd26060d2c Mon Sep 17 00:00:00 2001 From: Nathan Houghton Date: Sat, 21 Oct 2023 20:23:28 -0700 Subject: [PATCH] tests/dd: Do not use the OS provided dd utility on FIFOs On *BSD and macOS, the system provided dd utility opens up the output file for both reading and writing. This means that the open/write to the FIFO does not block, and almost instantly completes. The system dd then exits, leaving nothing left to be read by the time the coreutils-rs dd tries to open/read the FIFO. Avoid this problem by just writing to the FIFO from the test case itself, rather than relying on the system provide dd. --- tests/by-util/test_dd.rs | 72 ++++++++++++---------------------------- 1 file changed, 22 insertions(+), 50 deletions(-) diff --git a/tests/by-util/test_dd.rs b/tests/by-util/test_dd.rs index 8ebf57c1c..f560e3526 100644 --- a/tests/by-util/test_dd.rs +++ b/tests/by-util/test_dd.rs @@ -15,8 +15,6 @@ use regex::Regex; use std::fs::{File, OpenOptions}; use std::io::{BufReader, Read, Write}; use std::path::PathBuf; -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "freebsd")))] -use std::process::{Command, Stdio}; #[cfg(not(windows))] use std::thread::sleep; #[cfg(not(windows))] @@ -1459,74 +1457,48 @@ fn test_sparse() { assert_eq!(at.metadata("infile").len(), at.metadata("outfile").len()); } -// TODO These FIFO tests should work on macos, but some issue is -// causing our implementation of dd to wait indefinitely when it -// shouldn't. - /// Test that a seek on an output FIFO results in a read. #[test] -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "freebsd")))] +#[cfg(unix)] fn test_seek_output_fifo() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; at.mkfifo("fifo"); - // TODO When `dd` is a bit more advanced, we could use the uutils - // version of dd here as well. - let child = Command::new("dd") - .current_dir(&at.subdir) - .args([ - "count=1", - "if=/dev/zero", - &format!("of={}", at.plus_as_string("fifo")), - "status=noxfer", - ]) - .stderr(Stdio::piped()) - .spawn() - .expect("failed to execute child process"); - - ts.ucmd() + let mut ucmd = ts.ucmd(); + let child = ucmd .args(&["count=0", "seek=1", "of=fifo", "status=noxfer"]) - .succeeds() - .stderr_only("0+0 records in\n0+0 records out\n"); + .run_no_wait(); - let output = child.wait_with_output().unwrap(); - assert!(output.status.success()); - assert!(output.stdout.is_empty()); - assert_eq!(&output.stderr, b"1+0 records in\n1+0 records out\n"); + std::fs::write(at.plus("fifo"), &vec![0; 512]).unwrap(); + + child + .wait() + .unwrap() + .success() + .stderr_only("0+0 records in\n0+0 records out\n"); } /// Test that a skip on an input FIFO results in a read. #[test] -#[cfg(all(unix, not(target_os = "macos"), not(target_os = "freebsd")))] +#[cfg(unix)] fn test_skip_input_fifo() { let ts = TestScenario::new(util_name!()); let at = &ts.fixtures; at.mkfifo("fifo"); - // TODO When `dd` is a bit more advanced, we could use the uutils - // version of dd here as well. - let child = Command::new("dd") - .current_dir(&at.subdir) - .args([ - "count=1", - "if=/dev/zero", - &format!("of={}", at.plus_as_string("fifo")), - "status=noxfer", - ]) - .stderr(Stdio::piped()) - .spawn() - .expect("failed to execute child process"); - - ts.ucmd() + let mut ucmd = ts.ucmd(); + let child = ucmd .args(&["count=0", "skip=1", "if=fifo", "status=noxfer"]) - .succeeds() - .stderr_only("0+0 records in\n0+0 records out\n"); + .run_no_wait(); - let output = child.wait_with_output().unwrap(); - assert!(output.status.success()); - assert!(output.stdout.is_empty()); - assert_eq!(&output.stderr, b"1+0 records in\n1+0 records out\n"); + std::fs::write(at.plus("fifo"), &vec![0; 512]).unwrap(); + + child + .wait() + .unwrap() + .success() + .stderr_only("0+0 records in\n0+0 records out\n"); } /// Test for reading part of stdin from each of two child processes.