59 lines
1.8 KiB
Rust
59 lines
1.8 KiB
Rust
// Unix-only tests for with_suppressed_stderr restoring file descriptors
|
|
// Skip on Windows and non-Unix targets.
|
|
|
|
#![cfg(unix)]
|
|
|
|
use std::panic::{catch_unwind, AssertUnwindSafe};
|
|
|
|
fn stat_of_fd(fd: i32) -> (u64, u64) {
|
|
unsafe {
|
|
let mut st: libc::stat = std::mem::zeroed();
|
|
let r = libc::fstat(fd, &mut st as *mut libc::stat);
|
|
assert_eq!(r, 0, "fstat failed on fd {fd}");
|
|
(st.st_dev as u64, st.st_ino as u64)
|
|
}
|
|
}
|
|
|
|
fn stat_of_path(path: &str) -> (u64, u64) {
|
|
use std::ffi::CString;
|
|
unsafe {
|
|
let c = CString::new(path).unwrap();
|
|
let fd = libc::open(c.as_ptr(), libc::O_RDONLY);
|
|
assert!(fd >= 0, "failed to open {path}");
|
|
let s = stat_of_fd(fd);
|
|
let _ = libc::close(fd);
|
|
s
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn stderr_is_redirected_and_restored() {
|
|
let before = stat_of_fd(2);
|
|
let devnull = stat_of_path("/dev/null");
|
|
|
|
// During the call, fd 2 should be /dev/null; after, restored to before
|
|
polyscribe::with_suppressed_stderr(|| {
|
|
let inside = stat_of_fd(2);
|
|
assert_eq!(inside, devnull, "stderr should point to /dev/null during suppression");
|
|
// This write should be suppressed
|
|
eprintln!("this should be suppressed");
|
|
});
|
|
|
|
let after = stat_of_fd(2);
|
|
assert_eq!(after, before, "stderr should be restored after suppression");
|
|
}
|
|
|
|
#[test]
|
|
fn stderr_is_restored_even_if_closure_panics() {
|
|
let before = stat_of_fd(2);
|
|
let res = catch_unwind(AssertUnwindSafe(|| {
|
|
polyscribe::with_suppressed_stderr(|| {
|
|
// Trigger a deliberate panic inside the closure
|
|
panic!("boom inside with_suppressed_stderr");
|
|
});
|
|
}));
|
|
assert!(res.is_err(), "expected panic to propagate");
|
|
let after = stat_of_fd(2);
|
|
assert_eq!(after, before, "stderr should be restored after panic");
|
|
}
|