Skip to content

Commit 8f02d44

Browse files
committed
Fix --nocapture for run-make tests
This was confusing because there are three layers of output hiding. 1. libtest shoves all output into a buffer and does not print it unless the test fails or `--nocapture` is passed. 2. compiletest chooses whether to print the output from any given process. 3. run-make-support chooses what output to print. This modifies 2 and 3. - compiletest: Don't require both `--verbose` and `--nocapture` to show the output of run-make tests. - compiletest: Print the output from `rmake` processes if they succeed. Previously this was only printed on failure. - compiletest: Distinguish rustc and rmake stderr by printing the command name (e.g. "--stderr--" to "--rustc stderr--"). - run-make-support: Unconditionally print the needle/haystack being searched. Previously this was only printed on failure. Before: ``` $ x t tests/run-make/linker-warning --force-rerun -- --nocapture running 1 tests . test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 377 filtered out; finished in 281.64ms $ x t tests/run-make/linker-warning --force-rerun -v -- --nocapture 2>&1 | wc -l 1004 $ x t tests/run-make/linker-warning --force-rerun -v -- --nocapture | tail -n40 running 1 tests ------stdout------------------------------ ------stderr------------------------------ warning: unused import: `std::path::Path` --> /home/jyn/src/rust2/tests/run-make/linker-warning/rmake.rs:1:5 | 1 | use std::path::Path; | ^^^^^^^^^^^^^^^ | = note: `#[warn(unused_imports)]` on by default warning: unused import: `run_make_support::rfs::remove_file` --> /home/jyn/src/rust2/tests/run-make/linker-warning/rmake.rs:3:5 | 3 | use run_make_support::rfs::remove_file; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: 2 warnings emitted ------------------------------------------ test [run-make] tests/run-make/linker-warning ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 377 filtered out; finished in 285.89ms ``` After: ``` Testing stage1 compiletest suite=run-make mode=run-make (x86_64-unknown-linux-gnu) running 1 tests ------rmake stdout------------------------------ ------rmake stderr------------------------------ assert_contains_regex: === HAYSTACK === error: linking with `./fake-linker` failed: exit status: 1 | = note: LC_ALL="C" PATH="/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/bin:...:/bin" VSLANG="1033" "./fake-linker" "-m64" "/tmp/rustcYqdAZT/symbols.o" "main.main.d17f5fbe6225cf88-cgu.0.rcgu.o" "main.2uoctswmurc6ir5rvoay0p9ke.rcgu.o" "-Wl,--as-needed" "-Wl,-Bstatic" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-B/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/bin/gcc-ld" "-fuse-ld=lld" "-Wl,--eh-frame-hdr" "-Wl,-z,noexecstack" "-L" "/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/test/run-make/linker-warning/rmake_out" "-L" "/home/jyn/src/rust2/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "main" "-Wl,--gc-sections" "-pie" "-Wl,-z,relro,-z,now" "-nodefaultlibs" "run_make_error" = note: error: baz error: aborting due to 1 previous error === NEEDLE === fake-linker.*run_make_error assert_not_contains_regex: === HAYSTACK === === NEEDLE === fake-linker.*run_make_error ------------------------------------------ . test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 377 filtered out; finished in 314.81ms ```
1 parent 5bbbc09 commit 8f02d44

File tree

3 files changed

+54
-55
lines changed

3 files changed

+54
-55
lines changed

src/tools/compiletest/src/runtest.rs

+25-14
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,12 @@ impl<'test> TestCx<'test> {
407407
truncated: Truncated::No,
408408
cmdline: format!("{cmd:?}"),
409409
};
410-
self.dump_output(&proc_res.stdout, &proc_res.stderr);
410+
self.dump_output(
411+
self.config.verbose,
412+
&cmd.get_program().to_string_lossy(),
413+
&proc_res.stdout,
414+
&proc_res.stderr,
415+
);
411416

412417
proc_res
413418
}
@@ -1398,7 +1403,12 @@ impl<'test> TestCx<'test> {
13981403
cmdline,
13991404
};
14001405

1401-
self.dump_output(&result.stdout, &result.stderr);
1406+
self.dump_output(
1407+
self.config.verbose,
1408+
&command.get_program().to_string_lossy(),
1409+
&result.stdout,
1410+
&result.stderr,
1411+
);
14021412

14031413
result
14041414
}
@@ -1813,12 +1823,23 @@ impl<'test> TestCx<'test> {
18131823
}
18141824
}
18151825

1816-
fn dump_output(&self, out: &str, err: &str) {
1826+
fn dump_output(&self, print_output: bool, proc_name: &str, out: &str, err: &str) {
18171827
let revision = if let Some(r) = self.revision { format!("{}.", r) } else { String::new() };
18181828

18191829
self.dump_output_file(out, &format!("{}out", revision));
18201830
self.dump_output_file(err, &format!("{}err", revision));
1821-
self.maybe_dump_to_stdout(out, err);
1831+
1832+
if !print_output {
1833+
return;
1834+
}
1835+
1836+
// NOTE: this code is called from a libtest thread, so it's hidden by default unless --nocapture is passed or the test fails.
1837+
let proc_name = Path::new(proc_name).file_name().unwrap().to_string_lossy();
1838+
println!("------{proc_name} stdout------------------------------");
1839+
println!("{}", out);
1840+
println!("------{proc_name} stderr------------------------------");
1841+
println!("{}", err);
1842+
println!("------------------------------------------");
18221843
}
18231844

18241845
fn dump_output_file(&self, out: &str, extension: &str) {
@@ -1871,16 +1892,6 @@ impl<'test> TestCx<'test> {
18711892
output_base_name(self.config, self.testpaths, self.safe_revision())
18721893
}
18731894

1874-
fn maybe_dump_to_stdout(&self, out: &str, err: &str) {
1875-
if self.config.verbose {
1876-
println!("------stdout------------------------------");
1877-
println!("{}", out);
1878-
println!("------stderr------------------------------");
1879-
println!("{}", err);
1880-
println!("------------------------------------------");
1881-
}
1882-
}
1883-
18841895
fn error(&self, err: &str) {
18851896
match self.revision {
18861897
Some(rev) => println!("\nerror in revision `{}`: {}", rev, err),

src/tools/compiletest/src/runtest/run_make.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -517,14 +517,12 @@ impl TestCx<'_> {
517517

518518
let proc = disable_error_reporting(|| cmd.spawn().expect("failed to spawn `rmake`"));
519519
let (Output { stdout, stderr, status }, truncated) = self.read2_abbreviated(proc);
520+
let stdout = String::from_utf8_lossy(&stdout).into_owned();
521+
let stderr = String::from_utf8_lossy(&stderr).into_owned();
522+
// This conditions on `status.success()` so we don't print output twice on error.
523+
self.dump_output(status.success(), &cmd.get_program().to_string_lossy(), &stdout, &stderr);
520524
if !status.success() {
521-
let res = ProcRes {
522-
status,
523-
stdout: String::from_utf8_lossy(&stdout).into_owned(),
524-
stderr: String::from_utf8_lossy(&stderr).into_owned(),
525-
truncated,
526-
cmdline: format!("{:?}", cmd),
527-
};
525+
let res = ProcRes { status, stdout, stderr, truncated, cmdline: format!("{:?}", cmd) };
528526
self.fatal_proc_rec("rmake recipe failed to complete", &res);
529527
}
530528
}

src/tools/run-make-support/src/assertion_helpers.rs

+24-34
Original file line numberDiff line numberDiff line change
@@ -5,88 +5,78 @@ use std::path::Path;
55

66
use crate::{fs, regex};
77

8+
fn print<'a, 'e, A: AsRef<str>, E: AsRef<str>>(
9+
assertion_kind: &str,
10+
haystack: &'a A,
11+
needle: &'e E,
12+
) -> (&'a str, &'e str) {
13+
let haystack = haystack.as_ref();
14+
let needle = needle.as_ref();
15+
eprintln!("{assertion_kind}:");
16+
eprintln!("=== HAYSTACK ===");
17+
eprintln!("{}", haystack);
18+
eprintln!("=== NEEDLE ===");
19+
eprintln!("{}", needle);
20+
(haystack, needle)
21+
}
22+
823
/// Assert that `actual` is equal to `expected`.
924
#[track_caller]
1025
pub fn assert_equals<A: AsRef<str>, E: AsRef<str>>(actual: A, expected: E) {
1126
let actual = actual.as_ref();
1227
let expected = expected.as_ref();
28+
eprintln!("=== ACTUAL TEXT ===");
29+
eprintln!("{}", actual);
30+
eprintln!("=== EXPECTED ===");
31+
eprintln!("{}", expected);
1332
if actual != expected {
14-
eprintln!("=== ACTUAL TEXT ===");
15-
eprintln!("{}", actual);
16-
eprintln!("=== EXPECTED ===");
17-
eprintln!("{}", expected);
1833
panic!("expected text was not found in actual text");
1934
}
2035
}
2136

2237
/// Assert that `haystack` contains `needle`.
2338
#[track_caller]
2439
pub fn assert_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
25-
let haystack = haystack.as_ref();
26-
let needle = needle.as_ref();
40+
let (haystack, needle) = print("assert_contains", &haystack, &needle);
2741
if !haystack.contains(needle) {
28-
eprintln!("=== HAYSTACK ===");
29-
eprintln!("{}", haystack);
30-
eprintln!("=== NEEDLE ===");
31-
eprintln!("{}", needle);
3242
panic!("needle was not found in haystack");
3343
}
3444
}
3545

3646
/// Assert that `haystack` does not contain `needle`.
3747
#[track_caller]
3848
pub fn assert_not_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
39-
let haystack = haystack.as_ref();
40-
let needle = needle.as_ref();
49+
let (haystack, needle) = print("assert_not_contains", &haystack, &needle);
4150
if haystack.contains(needle) {
42-
eprintln!("=== HAYSTACK ===");
43-
eprintln!("{}", haystack);
44-
eprintln!("=== NEEDLE ===");
45-
eprintln!("{}", needle);
4651
panic!("needle was unexpectedly found in haystack");
4752
}
4853
}
4954

5055
/// Assert that `haystack` contains the regex pattern `needle`.
5156
#[track_caller]
5257
pub fn assert_contains_regex<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
53-
let haystack = haystack.as_ref();
54-
let needle = needle.as_ref();
58+
let (haystack, needle) = print("assert_contains_regex", &haystack, &needle);
5559
let re = regex::Regex::new(needle).unwrap();
5660
if !re.is_match(haystack) {
57-
eprintln!("=== HAYSTACK ===");
58-
eprintln!("{}", haystack);
59-
eprintln!("=== NEEDLE ===");
60-
eprintln!("{}", needle);
6161
panic!("needle was not found in haystack");
6262
}
6363
}
6464

6565
/// Assert that `haystack` does not contain the regex pattern `needle`.
6666
#[track_caller]
6767
pub fn assert_not_contains_regex<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
68-
let haystack = haystack.as_ref();
69-
let needle = needle.as_ref();
68+
let (haystack, needle) = print("assert_not_contains_regex", &haystack, &needle);
7069
let re = regex::Regex::new(needle).unwrap();
7170
if re.is_match(haystack) {
72-
eprintln!("=== HAYSTACK ===");
73-
eprintln!("{}", haystack);
74-
eprintln!("=== NEEDLE ===");
75-
eprintln!("{}", needle);
7671
panic!("needle was unexpectedly found in haystack");
7772
}
7873
}
7974

8075
/// Assert that `haystack` contains `needle` a `count` number of times.
8176
#[track_caller]
8277
pub fn assert_count_is<H: AsRef<str>, N: AsRef<str>>(count: usize, haystack: H, needle: N) {
83-
let haystack = haystack.as_ref();
84-
let needle = needle.as_ref();
78+
let (haystack, needle) = print("assert_count_is", &haystack, &needle);
8579
if count != haystack.matches(needle).count() {
86-
eprintln!("=== HAYSTACK ===");
87-
eprintln!("{}", haystack);
88-
eprintln!("=== NEEDLE ===");
89-
eprintln!("{}", needle);
9080
panic!("needle did not appear {count} times in haystack");
9181
}
9282
}

0 commit comments

Comments
 (0)