Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
use std::io::{stdout, Write};
use std::io::{stdout, ErrorKind, Write};
use std::path::{Path, PathBuf};

use public_api::diff::PublicItemsDiff;
use public_api::{public_api_from_rustdoc_json_str, Options, MINIMUM_RUSTDOC_JSON_VERSION};

type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
#[derive(thiserror::Error, Debug)]
enum Error {
#[error(transparent)]
PublicApiError(#[from] public_api::Error),
#[error(transparent)]
StdIoError(#[from] std::io::Error),
}

type Result<T> = std::result::Result<T, Error>;

#[derive(Default)]
struct Args {
Expand All @@ -13,7 +21,7 @@ struct Args {
files: Vec<PathBuf>,
}

fn main() -> Result<()> {
fn main_() -> Result<()> {
let args = args();

let mut options = Options::default();
Expand Down Expand Up @@ -155,3 +163,11 @@ fn args() -> Args {

args
}

/// Wrapper to handle <https://github.com/rust-lang/rust/issues/46016>
fn main() -> Result<()> {
match main_() {
Err(Error::StdIoError(e)) if e.kind() == ErrorKind::BrokenPipe => std::process::exit(141),
result => result,
}
}
26 changes: 26 additions & 0 deletions tests/bin_tests.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::{io::BufRead, str::from_utf8};

use assert_cmd::Command;
use public_api::MINIMUM_RUSTDOC_JSON_VERSION;

Expand Down Expand Up @@ -120,6 +122,30 @@ Added:
);
}

/// Uses a bash one-liner to test that public-api gracefully handles
/// `std::io::ErrorKind::BrokenPipe`
#[test]
#[serial]
fn broken_pipe() {
// Use the JSON for a somewhat large API so the pipe has time to become closed
// before all output has been written to stdout
let large_api = rustdoc_json_path_for_crate("./tests/crates/comprehensive_api");

// Now setup the actual one-liner
let mut cmd = std::process::Command::new("bash");
cmd.args([
"-c",
&format!(
"./target/debug/public-api {} | head -n 1",
large_api.to_string_lossy(),
),
]);

// Run it and assert on that there was no error printed
assert_eq!(cmd.output().unwrap().stdout.lines().count(), 1);
assert_eq!(from_utf8(&cmd.output().unwrap().stderr), Ok(""));
}

#[test]
fn short_help() {
let mut cmd = Command::cargo_bin("public-api").unwrap();
Expand Down