blob: 3b58adc3b8cb50b981243318afa21445d248d532 [file] [log] [blame] [edit]
use crate::diff::{Diff, Render};
use crate::error::Error;
use crate::{normalize, term, Expected, Test};
use std::env;
use std::path::Path;
use std::process::Output;
use termcolor::Color::{self, *};
pub(crate) enum Level {
Fail,
Warn,
}
pub(crate) use self::Level::*;
pub(crate) fn prepare_fail(err: Error) {
if err.already_printed() {
return;
}
term::bold_color(Red);
print!("ERROR");
term::reset();
println!(": {}", err);
println!();
}
pub(crate) fn test_fail(err: Error) {
if err.already_printed() {
return;
}
term::bold_color(Red);
println!("error");
term::color(Red);
println!("{}", err);
term::reset();
println!();
}
pub(crate) fn no_tests_enabled() {
term::color(Yellow);
println!("There are no trybuild tests enabled yet.");
term::reset();
}
pub(crate) fn ok() {
term::color(Green);
println!("ok");
term::reset();
}
pub(crate) fn begin_test(test: &Test, show_expected: bool) {
let display_name = test.path.as_os_str().to_string_lossy();
print!("test ");
term::bold();
print!("{}", display_name);
term::reset();
if show_expected {
match test.expected {
Expected::Pass => print!(" [should pass]"),
Expected::CompileFail => print!(" [should fail to compile]"),
}
}
print!(" ... ");
}
pub(crate) fn failed_to_build(stderr: &str) {
term::bold_color(Red);
println!("error");
snippet(Red, stderr);
println!();
}
pub(crate) fn should_not_have_compiled() {
term::bold_color(Red);
println!("error");
term::color(Red);
println!("Expected test case to fail to compile, but it succeeded.");
term::reset();
println!();
}
pub(crate) fn write_stderr_wip(wip_path: &Path, stderr_path: &Path, stderr: &str) {
let wip_path = wip_path.to_string_lossy();
let stderr_path = stderr_path.to_string_lossy();
term::bold_color(Yellow);
println!("wip");
println!();
print!("NOTE");
term::reset();
println!(": writing the following output to `{}`.", wip_path);
println!(
"Move this file to `{}` to accept it as correct.",
stderr_path,
);
snippet(Yellow, stderr);
println!();
}
pub(crate) fn overwrite_stderr(stderr_path: &Path, stderr: &str) {
let stderr_path = stderr_path.to_string_lossy();
term::bold_color(Yellow);
println!("wip");
println!();
print!("NOTE");
term::reset();
println!(": writing the following output to `{}`.", stderr_path);
snippet(Yellow, stderr);
println!();
}
pub(crate) fn mismatch(expected: &str, actual: &str) {
term::bold_color(Red);
println!("mismatch");
term::reset();
println!();
let diff = if env::var_os("TERM").map_or(true, |term| term == "dumb") {
// No diff in dumb terminal or when TERM is unset.
None
} else {
Diff::compute(expected, actual)
};
term::bold_color(Blue);
println!("EXPECTED:");
snippet_diff(Blue, expected, diff.as_ref());
println!();
term::bold_color(Red);
println!("ACTUAL OUTPUT:");
snippet_diff(Red, actual, diff.as_ref());
print!("note: If the ");
term::color(Red);
print!("actual output");
term::reset();
println!(" is the correct output you can bless it by rerunning");
println!(" your test with the environment variable TRYBUILD=overwrite");
println!();
}
pub(crate) fn output(warnings: &str, output: &Output) {
let success = output.status.success();
let stdout = normalize::trim(&output.stdout);
let stderr = normalize::trim(&output.stderr);
let has_output = !stdout.is_empty() || !stderr.is_empty();
if success {
ok();
if has_output || !warnings.is_empty() {
println!();
}
} else {
term::bold_color(Red);
println!("error");
term::color(Red);
if has_output {
println!("Test case failed at runtime.");
} else {
println!("Execution of the test case was unsuccessful but there was no output.");
}
term::reset();
println!();
}
self::warnings(warnings);
let color = if success { Yellow } else { Red };
for (name, content) in &[("STDOUT", stdout), ("STDERR", stderr)] {
if !content.is_empty() {
term::bold_color(color);
println!("{}:", name);
snippet(color, &normalize::trim(content));
println!();
}
}
}
pub(crate) fn fail_output(level: Level, stdout: &[u8]) {
let color = match level {
Fail => Red,
Warn => Yellow,
};
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;
}
term::bold_color(Yellow);
println!("WARNINGS:");
snippet(Yellow, warnings);
println!();
}
fn snippet(color: Color, content: &str) {
snippet_diff(color, content, None);
}
fn snippet_diff(color: Color, content: &str, diff: Option<&Diff>) {
fn dotted_line() {
println!("{}", "┈".repeat(60));
}
term::color(color);
dotted_line();
match diff {
Some(diff) => {
for chunk in diff.iter(content) {
match chunk {
Render::Common(s) => {
term::color(color);
print!("{}", s);
}
Render::Unique(s) => {
term::bold_color(color);
print!("\x1B[7m{}", s);
}
}
}
}
None => print!("{}", content),
}
term::color(color);
dotted_line();
term::reset();
}