From 3f0c788aed7e4a3804b099ed1dba23c038d3ee5d Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 8 Nov 2018 17:40:08 -0800 Subject: [PATCH] Show error on JSON parse error and nonzero exit. --- src/cargo/util/process_builder.rs | 18 ++++---- tests/testsuite/build.rs | 68 +++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/src/cargo/util/process_builder.rs b/src/cargo/util/process_builder.rs index 26655d31fdd..ca44042c33b 100644 --- a/src/cargo/util/process_builder.rs +++ b/src/cargo/util/process_builder.rs @@ -5,6 +5,7 @@ use std::fmt; use std::path::Path; use std::process::{Command, Output, Stdio}; +use failure::Fail; use jobserver::Client; use shell_escape::escape; @@ -271,19 +272,20 @@ impl ProcessBuilder { { let to_print = if capture_output { Some(&output) } else { None }; - if !output.status.success() { - return Err(process_error( - &format!("process didn't exit successfully: {}", self), - Some(output.status), - to_print, - ).into()); - } else if let Some(e) = callback_error { + if let Some(e) = callback_error { let cx = process_error( &format!("failed to parse process output: {}", self), Some(output.status), to_print, ); - return Err(e.context(cx).into()); + return Err(cx.context(e).into()); + } else if !output.status.success() { + return Err(process_error( + &format!("process didn't exit successfully: {}", self), + Some(output.status), + to_print, + ) + .into()); } } diff --git a/tests/testsuite/build.rs b/tests/testsuite/build.rs index 5f5a69c8e38..dc72669a48c 100644 --- a/tests/testsuite/build.rs +++ b/tests/testsuite/build.rs @@ -4435,3 +4435,71 @@ Caused by: .with_status(101) .run(); } + +#[test] +fn json_parse_fail() { + // Ensure when json parsing fails, and rustc exits with non-zero exit + // code, that a useful error message is displayed. + let foo = project() + .file( + "Cargo.toml", + r#" + [package] + name = "foo" + version = "0.1.0" + [dependencies] + pm = { path = "pm" } + "#, + ) + .file( + "src/lib.rs", + r#" + #[macro_use] + extern crate pm; + + #[derive(Foo)] + pub struct S; + "#, + ) + .file( + "pm/Cargo.toml", + r#" + [package] + name = "pm" + version = "0.1.0" + [lib] + proc-macro = true + "#, + ) + .file( + "pm/src/lib.rs", + r#" + extern crate proc_macro; + use proc_macro::TokenStream; + + #[proc_macro_derive(Foo)] + pub fn derive(_input: TokenStream) -> TokenStream { + eprintln!("{{evil proc macro}}"); + panic!("something went wrong"); + } + "#, + ) + .build(); + + foo.cargo("build --message-format=json") + .with_stderr( + "\ +[COMPILING] pm [..] +[COMPILING] foo [..] +[ERROR] Could not compile `foo`. + +Caused by: + compiler produced invalid json: `{evil proc macro}` + +Caused by: + failed to parse process output: `rustc [..] +", + ) + .with_status(101) + .run(); +}