diff --git a/.gitignore b/.gitignore index 6936990..98e5fcf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -/target +target **/*.rs.bk Cargo.lock diff --git a/Cargo.toml b/Cargo.toml index 98b8e13..2c2f64f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,6 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" termcolor = "1.0" toml = "0.5" + +[dev-dependencies] +derive_mac = { path = "tests/stdout/derive_mac" } diff --git a/src/message.rs b/src/message.rs index e96707a..b127bd2 100644 --- a/src/message.rs +++ b/src/message.rs @@ -170,6 +170,18 @@ pub(crate) fn output(warnings: &str, output: &Output) { } } +pub(crate) fn fail_output(exit: bool, output: &normalize::Variations) { + let stdout = output.stdout(); + let color = if !exit { Yellow } else { Red }; + + if !stdout.is_empty() { + term::bold_color(color); + println!("STDOUT:"); + snippet(color, &normalize::trim(stdout)); + println!(); + } +} + pub(crate) fn warnings(warnings: &str) { if warnings.is_empty() { return; diff --git a/src/normalize.rs b/src/normalize.rs index 7fa8ab3..b6b7f0a 100644 --- a/src/normalize.rs +++ b/src/normalize.rs @@ -12,35 +12,47 @@ pub fn trim>(output: S) -> String { normalized } -pub fn diagnostics(output: Vec) -> Variations { - let mut from_bytes = String::from_utf8_lossy(&output).to_string(); - from_bytes = from_bytes.replace("\r\n", "\n"); +pub fn diagnostics(output: &std::process::Output) -> Variations { + let mut err_from_bytes = String::from_utf8_lossy(&output.stderr).to_string(); + err_from_bytes = err_from_bytes.replace("\r\n", "\n"); - let variations = [Basic, StripCouldNotCompile] + let out_from_bytes = String::from_utf8_lossy(&output.stdout); + let variations_out = out_from_bytes.replace("\r\n", "\n"); + + let variations_err = [Basic, StripCouldNotCompile] .iter() - .map(|normalization| apply(&from_bytes, *normalization)) + .map(|normalization| apply(&err_from_bytes, *normalization)) .collect(); - Variations { variations } + Variations { + variations_err, + variations_out, + } } pub struct Variations { - variations: Vec, + variations_err: Vec, + variations_out: String, } impl Variations { pub fn map String>(self, f: F) -> Self { Variations { - variations: self.variations.into_iter().map(f).collect(), + variations_err: self.variations_err.into_iter().map(f).collect(), + variations_out: self.variations_out, } } pub fn preferred(&self) -> &str { - self.variations.last().unwrap() + self.variations_err.last().unwrap() } pub fn any bool>(&self, mut f: F) -> bool { - self.variations.iter().any(|stderr| f(stderr)) + self.variations_err.iter().any(|stderr| f(stderr)) + } + + pub fn stdout(&self) -> &str { + self.variations_out.as_str() } } diff --git a/src/run.rs b/src/run.rs index 2d786b5..fecd689 100644 --- a/src/run.rs +++ b/src/run.rs @@ -198,7 +198,8 @@ impl Test { let output = cargo::build_test(project, name)?; let success = output.status.success(); - let stderr = normalize::diagnostics(output.stderr).map(|stderr| { + + let stdio = normalize::diagnostics(&output).map(|stderr| { stderr .replace(&name.0, "$CRATE") .replace(project.source_dir.to_string_lossy().as_ref(), "$DIR") @@ -209,7 +210,7 @@ impl Test { Expected::CompileFail => Test::check_compile_fail, }; - check(self, project, name, success, stderr) + check(self, project, name, success, stdio) } fn check_pass( @@ -220,15 +221,23 @@ impl Test { variations: Variations, ) -> Result<()> { let preferred = variations.preferred(); + // from build output (for proc-macro output) + let build_stdout = variations.stdout(); if !success { message::failed_to_build(preferred); return Err(Error::CargoFail); } - let output = cargo::run_test(project, name)?; - message::output(preferred, &output); + let mut output = cargo::run_test(project, name)?; + output.stdout = format!( + "{}\n{}", + build_stdout, + String::from_utf8_lossy(&output.stdout) + ) + .into_bytes(); + message::output(preferred, &output); if output.status.success() { Ok(()) } else { @@ -247,10 +256,11 @@ impl Test { if success { message::should_not_have_compiled(); + message::fail_output(success, &variations); message::warnings(preferred); return Err(Error::ShouldNotHaveCompiled); } - + let stderr_path = self.path.with_extension("stderr"); if !stderr_path.exists() { @@ -272,6 +282,7 @@ impl Test { fs::write(stderr_path, preferred).map_err(Error::WriteStderr)?; } } + message::fail_output(success, &variations); return Ok(()); } @@ -281,6 +292,7 @@ impl Test { if variations.any(|stderr| expected == stderr) { message::ok(); + return Ok(()); } diff --git a/tests/stdout.rs b/tests/stdout.rs new file mode 100644 index 0000000..a6910cb --- /dev/null +++ b/tests/stdout.rs @@ -0,0 +1,7 @@ +#[test] +fn test() { + let t = trybuild::TestCases::new(); + t.pass("tests/stdout/print-pass.rs"); + t.compile_fail("tests/stdout/print-fail.rs"); + t.compile_fail("tests/stdout/run-fail.rs"); +} diff --git a/tests/stdout/derive_mac/Cargo.toml b/tests/stdout/derive_mac/Cargo.toml new file mode 100644 index 0000000..720feed --- /dev/null +++ b/tests/stdout/derive_mac/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "derive_mac" +version = "0.0.0" +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +syn = "0.15" +quote = "0.6" \ No newline at end of file diff --git a/tests/stdout/derive_mac/src/lib.rs b/tests/stdout/derive_mac/src/lib.rs new file mode 100644 index 0000000..f4fabfc --- /dev/null +++ b/tests/stdout/derive_mac/src/lib.rs @@ -0,0 +1,16 @@ +extern crate proc_macro; + +use proc_macro::TokenStream; +use syn::{parse_macro_input, DeriveInput}; +use quote::quote; + +#[proc_macro_derive(Print)] +pub fn derive(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + let name = input.ident.clone(); + println!("IN PROC-MACRO"); + + proc_macro::TokenStream::from(quote!{ + impl #name {} + }) +} \ No newline at end of file diff --git a/tests/stdout/print-fail.rs b/tests/stdout/print-fail.rs new file mode 100644 index 0000000..3b738ff --- /dev/null +++ b/tests/stdout/print-fail.rs @@ -0,0 +1,11 @@ +use derive_mac::Print; + +#[derive(Print)] +pub struct Field { + name: &'static str, + bitmask: u16, +} + +compile_error!("ERROR"); + +fn main() {} \ No newline at end of file diff --git a/tests/stdout/print-pass.rs b/tests/stdout/print-pass.rs new file mode 100644 index 0000000..6ce238b --- /dev/null +++ b/tests/stdout/print-pass.rs @@ -0,0 +1,12 @@ +use derive_mac::Print; + +#[derive(Print)] +pub struct Field { + name: &'static str, + bitmask: u16, +} + +fn main() { + println!("IN PRINTLN.RS"); + assert!(true) +} \ No newline at end of file diff --git a/tests/stdout/run-fail.rs b/tests/stdout/run-fail.rs new file mode 100644 index 0000000..87cb439 --- /dev/null +++ b/tests/stdout/run-fail.rs @@ -0,0 +1,9 @@ +use derive_mac::Print; + +#[derive(Print)] +pub struct Field { + name: &'static str, + bitmask: u16, +} + +fn main() {} \ No newline at end of file