use crate::cli::doctor::{DoctorArgs, run};
struct ClosedPipe;
impl std::io::Write for ClosedPipe {
fn write(&mut self, _buf: &[u8]) -> std::io::Result<usize> {
Err(std::io::Error::new(
std::io::ErrorKind::BrokenPipe,
"closed",
))
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
struct BadDisk;
impl std::io::Write for BadDisk {
fn write(&mut self, _buf: &[u8]) -> std::io::Result<usize> {
Err(std::io::Error::other("disk on fire"))
}
fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
}
#[tokio::test]
async fn a_closed_pipe_is_not_a_failure_but_a_real_write_error_is() {
let dir = tempfile::tempdir().expect("tempdir");
std::fs::write(dir.path().join("a.py"), "x = 1\n").expect("a.py");
let args = DoctorArgs {
path: dir.path().to_path_buf(),
config: None,
};
let mut sink = ClosedPipe;
assert!(
super::run_scoped(&mut sink, &args, dir.path())
.await
.is_err(),
"run_to reports the write failure to its caller"
);
assert_eq!(
run(&args).await.expect("stdout is a real sink here"),
crate::Exit::Clean
);
let mut sink = BadDisk;
let err = super::run_scoped(&mut sink, &args, dir.path())
.await
.expect_err("a real IO error must surface");
assert!(
!crate::cli::doctor::is_broken_pipe(&err),
"a disk error is not a closed pipe"
);
let mut sink = ClosedPipe;
let err = super::run_scoped(&mut sink, &args, dir.path())
.await
.expect_err("closed pipe");
assert!(
crate::cli::doctor::is_broken_pipe(&err),
"and a closed pipe is"
);
}