trybuild_internals_api/
message.rs

1use crate::diff::{Diff, Render};
2use crate::error::Error;
3use crate::{normalize, term, Expected, Test};
4use std::env;
5use std::path::Path;
6use std::process::Output;
7use termcolor::Color::{self, *};
8
9pub enum Level {
10    Fail,
11    Warn,
12}
13
14pub use self::Level::*;
15
16pub fn prepare_fail(err: Error) {
17    if err.already_printed() {
18        return;
19    }
20
21    term::bold_color(Red);
22    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("ERROR"));
};print!("ERROR");
23    term::reset();
24    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!(": {0}\n", err));
};println!(": {}", err);
25    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
26}
27
28pub fn test_fail(err: Error) {
29    if err.already_printed() {
30        return;
31    }
32
33    term::bold_color(Red);
34    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("error\n"));
};println!("error");
35    term::color(Red);
36    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("{0}\n", err));
};println!("{}", err);
37    term::reset();
38    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
39}
40
41pub fn no_tests_enabled() {
42    term::color(Yellow);
43    {
    use std::io::Write;
    let _ =
        crate::term::lock().write_fmt(format_args!("There are no trybuild tests enabled yet.\n"));
};println!("There are no trybuild tests enabled yet.");
44    term::reset();
45}
46
47pub fn ok() {
48    term::color(Green);
49    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("ok\n"));
};println!("ok");
50    term::reset();
51}
52
53pub fn begin_test(test: &Test, show_expected: bool) {
54    let display_name = test.path.as_os_str().to_string_lossy();
55
56    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("test "));
};print!("test ");
57    term::bold();
58    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("{0}", display_name));
};print!("{}", display_name);
59    term::reset();
60
61    if show_expected {
62        match test.expected {
63            Expected::Pass => {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!(" [should pass]"));
}print!(" [should pass]"),
64            Expected::CompileFail => {
    use std::io::Write;
    let _ =
        crate::term::lock().write_fmt(format_args!(" [should fail to compile]"));
}print!(" [should fail to compile]"),
65        }
66    }
67
68    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!(" ... "));
};print!(" ... ");
69}
70
71pub fn failed_to_build(stderr: &str) {
72    term::bold_color(Red);
73    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("error\n"));
};println!("error");
74    snippet(Red, stderr);
75    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
76}
77
78pub fn should_not_have_compiled() {
79    term::bold_color(Red);
80    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("error\n"));
};println!("error");
81    term::color(Red);
82    {
    use std::io::Write;
    let _ =
        crate::term::lock().write_fmt(format_args!("Expected test case to fail to compile, but it succeeded.\n"));
};println!("Expected test case to fail to compile, but it succeeded.");
83    term::reset();
84    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
85}
86
87pub fn write_stderr_wip(wip_path: &Path, stderr_path: &Path, stderr: &str) {
88    let wip_path = wip_path.to_string_lossy();
89    let stderr_path = stderr_path.to_string_lossy();
90
91    term::bold_color(Yellow);
92    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("wip\n"));
};println!("wip");
93    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
94    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("NOTE"));
};print!("NOTE");
95    term::reset();
96    {
    use std::io::Write;
    let _ =
        crate::term::lock().write_fmt(format_args!(": writing the following output to `{0}`.\n",
                wip_path));
};println!(": writing the following output to `{}`.", wip_path);
97    {
    use std::io::Write;
    let _ =
        crate::term::lock().write_fmt(format_args!("Move this file to `{0}` to accept it as correct.\n",
                stderr_path));
};println!(
98        "Move this file to `{}` to accept it as correct.",
99        stderr_path,
100    );
101    snippet(Yellow, stderr);
102    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
103}
104
105pub fn overwrite_stderr(stderr_path: &Path, stderr: &str) {
106    let stderr_path = stderr_path.to_string_lossy();
107
108    term::bold_color(Yellow);
109    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("wip\n"));
};println!("wip");
110    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
111    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("NOTE"));
};print!("NOTE");
112    term::reset();
113    {
    use std::io::Write;
    let _ =
        crate::term::lock().write_fmt(format_args!(": writing the following output to `{0}`.\n",
                stderr_path));
};println!(": writing the following output to `{}`.", stderr_path);
114    snippet(Yellow, stderr);
115    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
116}
117
118pub fn mismatch(expected: &str, actual: &str) {
119    term::bold_color(Red);
120    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("mismatch\n"));
};println!("mismatch");
121    term::reset();
122    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
123    let diff = if env::var_os("TERM").map_or(true, |term| term == "dumb") {
124        // No diff in dumb terminal or when TERM is unset.
125        None
126    } else {
127        Diff::compute(expected, actual)
128    };
129    term::bold_color(Blue);
130    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("EXPECTED:\n"));
};println!("EXPECTED:");
131    snippet_diff(Blue, expected, diff.as_ref());
132    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
133    term::bold_color(Red);
134    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("ACTUAL OUTPUT:\n"));
};println!("ACTUAL OUTPUT:");
135    snippet_diff(Red, actual, diff.as_ref());
136    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("note: If the "));
};print!("note: If the ");
137    term::color(Red);
138    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("actual output"));
};print!("actual output");
139    term::reset();
140    {
    use std::io::Write;
    let _ =
        crate::term::lock().write_fmt(format_args!(" is the correct output you can bless it by rerunning\n"));
};println!(" is the correct output you can bless it by rerunning");
141    {
    use std::io::Write;
    let _ =
        crate::term::lock().write_fmt(format_args!("      your test with the environment variable TRYBUILD=overwrite\n"));
};println!("      your test with the environment variable TRYBUILD=overwrite");
142    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
143}
144
145pub fn output(warnings: &str, output: &Output) {
146    let success = output.status.success();
147    let stdout = normalize::trim(&output.stdout);
148    let stderr = normalize::trim(&output.stderr);
149    let has_output = !stdout.is_empty() || !stderr.is_empty();
150
151    if success {
152        ok();
153        if has_output || !warnings.is_empty() {
154            {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
155        }
156    } else {
157        term::bold_color(Red);
158        {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("error\n"));
};println!("error");
159        term::color(Red);
160        if has_output {
161            {
    use std::io::Write;
    let _ =
        crate::term::lock().write_fmt(format_args!("Test case failed at runtime.\n"));
};println!("Test case failed at runtime.");
162        } else {
163            {
    use std::io::Write;
    let _ =
        crate::term::lock().write_fmt(format_args!("Execution of the test case was unsuccessful but there was no output.\n"));
};println!("Execution of the test case was unsuccessful but there was no output.");
164        }
165        term::reset();
166        {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
167    }
168
169    self::warnings(warnings);
170
171    let color = if success { Yellow } else { Red };
172
173    for (name, content) in &[("STDOUT", stdout), ("STDERR", stderr)] {
174        if !content.is_empty() {
175            term::bold_color(color);
176            {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("{0}:\n", name));
};println!("{}:", name);
177            snippet(color, &normalize::trim(content));
178            {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
179        }
180    }
181}
182
183pub fn fail_output(level: Level, stdout: &str) {
184    let color = match level {
185        Fail => Red,
186        Warn => Yellow,
187    };
188
189    if !stdout.is_empty() {
190        term::bold_color(color);
191        {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("STDOUT:\n"));
};println!("STDOUT:");
192        snippet(color, &normalize::trim(stdout));
193        {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
194    }
195}
196
197pub fn warnings(warnings: &str) {
198    if warnings.is_empty() {
199        return;
200    }
201
202    term::bold_color(Yellow);
203    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("WARNINGS:\n"));
};println!("WARNINGS:");
204    snippet(Yellow, warnings);
205    {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\n"));
};println!();
206}
207
208fn snippet(color: Color, content: &str) {
209    snippet_diff(color, content, None);
210}
211
212fn snippet_diff(color: Color, content: &str, diff: Option<&Diff>) {
213    fn dotted_line() {
214        {
    use std::io::Write;
    let _ =
        crate::term::lock().write_fmt(format_args!("{0}\n",
                "┈".repeat(60)));
};println!("{}", "┈".repeat(60));
215    }
216
217    term::color(color);
218    dotted_line();
219
220    match diff {
221        Some(diff) => {
222            for chunk in diff.iter(content) {
223                match chunk {
224                    Render::Common(s) => {
225                        term::color(color);
226                        {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("{0}", s));
};print!("{}", s);
227                    }
228                    Render::Unique(s) => {
229                        term::bold_color(color);
230                        {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("\u{1b}[7m{0}", s));
};print!("\x1B[7m{}", s);
231                    }
232                }
233            }
234        }
235        None => {
    use std::io::Write;
    let _ = crate::term::lock().write_fmt(format_args!("{0}", content));
}print!("{}", content),
236    }
237
238    term::color(color);
239    dotted_line();
240    term::reset();
241}