aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/broken_pipe.rs49
1 files changed, 49 insertions, 0 deletions
diff --git a/tests/broken_pipe.rs b/tests/broken_pipe.rs
new file mode 100644
index 00000000..66aa029e
--- /dev/null
+++ b/tests/broken_pipe.rs
@@ -0,0 +1,49 @@
+#![cfg(unix)]
+
+use std::os::fd::{FromRawFd, OwnedFd};
+use std::os::unix::process::ExitStatusExt;
+use std::process::{Command, Output, Stdio};
+
+fn closed_pipe_writer() -> Stdio {
+ let mut fds = [-1; 2];
+ assert_eq!(unsafe { libc::pipe(fds.as_mut_ptr()) }, 0);
+ // SAFETY: pipe initialized both descriptors, and each is assigned to one
+ // OwnedFd so it is closed exactly once.
+ let read_fd = unsafe { OwnedFd::from_raw_fd(fds[0]) };
+ let write_fd = unsafe { OwnedFd::from_raw_fd(fds[1]) };
+ drop(read_fd);
+ Stdio::from(write_fd)
+}
+
+fn run_with_closed_stdout(args: &[&str]) -> Output {
+ Command::new(env!("CARGO_BIN_EXE_herdr"))
+ .args(args)
+ .stdout(closed_pipe_writer())
+ .stderr(Stdio::piped())
+ .output()
+ .expect("run herdr CLI")
+}
+
+fn assert_quiet_sigpipe(output: Output) {
+ assert_eq!(output.status.signal(), Some(libc::SIGPIPE));
+ assert!(
+ output.stderr.is_empty(),
+ "closed stdout should not emit an error or panic: {}",
+ String::from_utf8_lossy(&output.stderr)
+ );
+}
+
+#[test]
+fn cli_exits_via_sigpipe_without_panicking_when_stdout_closes() {
+ assert_quiet_sigpipe(run_with_closed_stdout(&["api", "schema", "--json"]));
+}
+
+#[test]
+fn terminal_help_uses_cli_sigpipe_behavior_before_attach_starts() {
+ assert_quiet_sigpipe(run_with_closed_stdout(&["terminal", "attach", "--help"]));
+}
+
+#[test]
+fn completion_direct_writer_uses_cli_sigpipe_behavior() {
+ assert_quiet_sigpipe(run_with_closed_stdout(&["completion", "bash"]));
+}