diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e74529..cfbb13d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## Unreleased +- Fix stderr copying to stdout bug (https://github.com/schneems/fun_run/pull/3) + ## 0.1.0 - First release diff --git a/Cargo.toml b/Cargo.toml index 6b3e315..749b6dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,3 +15,6 @@ regex = "1" [features] which_problem = ["dep:which_problem"] + +[dev-dependencies] +pretty_assertions = "1" diff --git a/src/command.rs b/src/command.rs index 7946949..2902386 100644 --- a/src/command.rs +++ b/src/command.rs @@ -23,7 +23,7 @@ pub(crate) fn output_and_write_streams( let stdout_thread = mem::take(&mut child.stdout).map(|mut child_stdout| { scope.spawn(move || std::io::copy(&mut child_stdout, &mut stdout)) }); - let stderr_thread = mem::take(&mut child.stdout).map(|mut child_stderr| { + let stderr_thread = mem::take(&mut child.stderr).map(|mut child_stderr| { scope.spawn(move || std::io::copy(&mut child_stderr, &mut stderr)) }); @@ -53,14 +53,43 @@ pub(crate) fn output_and_write_streams( }) } +/// Constructs a writer that writes to two other writers. Similar to the UNIX `tee` command. +pub(crate) fn tee(a: A, b: B) -> TeeWrite { + TeeWrite { + inner_a: a, + inner_b: b, + } +} + +/// A tee writer that was created with the [`tee`] function. +#[derive(Debug, Clone)] +pub(crate) struct TeeWrite { + inner_a: A, + inner_b: B, +} + +impl io::Write for TeeWrite { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.inner_a.write_all(buf)?; + self.inner_b.write_all(buf)?; + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + self.inner_a.flush()?; + self.inner_b.flush() + } +} + #[cfg(test)] mod test { use super::*; + use pretty_assertions::assert_str_eq; use std::process::Command; #[test] #[cfg(unix)] - fn test_output_and_write_streams() { + fn test_output_and_write_streams_stdout() { let mut stdout_buf = Vec::new(); let mut stderr_buf = Vec::new(); @@ -76,32 +105,18 @@ mod test { assert_eq!(output.stdout, "Hello World!".as_bytes()); assert_eq!(output.stderr, Vec::::new()); } -} -/// Constructs a writer that writes to two other writers. Similar to the UNIX `tee` command. -pub(crate) fn tee(a: A, b: B) -> TeeWrite { - TeeWrite { - inner_a: a, - inner_b: b, - } -} + #[test] + #[cfg(unix)] + fn test_output_and_write_streams_stderr() { + let mut stdout_buf = Vec::new(); + let mut stderr_buf = Vec::new(); -/// A tee writer that was created with the [`tee`] function. -#[derive(Debug, Clone)] -pub(crate) struct TeeWrite { - inner_a: A, - inner_b: B, -} + let mut cmd = Command::new("bash"); + cmd.args(["-c", "echo -n Hello World! >&2"]); -impl io::Write for TeeWrite { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.inner_a.write_all(buf)?; - self.inner_b.write_all(buf)?; - Ok(buf.len()) - } + let _ = output_and_write_streams(&mut cmd, &mut stdout_buf, &mut stderr_buf).unwrap(); - fn flush(&mut self) -> io::Result<()> { - self.inner_a.flush()?; - self.inner_b.flush() + assert_str_eq!(&String::from_utf8_lossy(&stderr_buf), "Hello World!"); } }