Skip to content

Commit 6667682

Browse files
committed
Auto merge of rust-lang#108659 - ferrocene:pa-test-metrics, r=Mark-Simulacrum
Include executed tests in the build metrics (and use a custom test display impl) The main goal of this PR is to include all tests executed in CI inside the build metrics JSON files. I need this for Ferrocene, and `@Mark-Simulacrum` expressed desire to have this as well to ensure all tests are executed at least once somewhere in CI. Unfortunately implementing this required rewriting inside of bootstrap all of the code to render the test output to console. libtest supports outputting JSON instead of raw text, which we can indeed use to populate the build metrics. Doing that suppresses the console output though, and compared to rustc and Cargo the console output is not included as a JSON field. Because of that, this PR had to reimplement both the "pretty" format (one test per line, with `rust.verbose-tests = true`), and the "terse" format (the wall of dots, with `rust.verbose-tests = false`). The current implementation should have the exact same output as libtest, except for the benchmark output. libtest's benchmark output is broken in the "terse" format, so since that's our default I slightly improved how it's rendered. Also, to bring parity with libtest I had to introduce support for coloring output from bootstrap, using the same dependencies `annotate-snippets` uses. It's now possible to use `builder.color_for_stdout(Color::Red, "text")` and `builder.color_for_stderr(Color::Green, "text")` across all of bootstrap, automatically respecting the `--color` flag and whether the stream is a terminal or not. I recommend reviewing the PR commit-by-commit. r? `@Mark-Simulacrum`
2 parents a01b4cc + aacbd86 commit 6667682

File tree

9 files changed

+504
-38
lines changed

9 files changed

+504
-38
lines changed

src/bootstrap/Cargo.lock

+22
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ dependencies = [
1111
"memchr",
1212
]
1313

14+
[[package]]
15+
name = "atty"
16+
version = "0.2.14"
17+
source = "registry+https://github.com/rust-lang/crates.io-index"
18+
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
19+
dependencies = [
20+
"hermit-abi",
21+
"libc",
22+
"winapi",
23+
]
24+
1425
[[package]]
1526
name = "autocfg"
1627
version = "1.1.0"
@@ -36,6 +47,7 @@ dependencies = [
3647
name = "bootstrap"
3748
version = "0.0.0"
3849
dependencies = [
50+
"atty",
3951
"build_helper",
4052
"cc",
4153
"cmake",
@@ -55,6 +67,7 @@ dependencies = [
5567
"sha2",
5668
"sysinfo",
5769
"tar",
70+
"termcolor",
5871
"toml",
5972
"walkdir",
6073
"windows",
@@ -636,6 +649,15 @@ dependencies = [
636649
"xattr",
637650
]
638651

652+
[[package]]
653+
name = "termcolor"
654+
version = "1.2.0"
655+
source = "registry+https://github.com/rust-lang/crates.io-index"
656+
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
657+
dependencies = [
658+
"winapi-util",
659+
]
660+
639661
[[package]]
640662
name = "thread_local"
641663
version = "1.1.4"

src/bootstrap/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ path = "bin/sccache-plus-cl.rs"
3030
test = false
3131

3232
[dependencies]
33+
atty = "0.2.14"
3334
build_helper = { path = "../tools/build_helper" }
3435
cmake = "0.1.38"
3536
filetime = "0.2"
@@ -45,6 +46,7 @@ serde_derive = "1.0.137"
4546
serde_json = "1.0.2"
4647
sha2 = "0.10"
4748
tar = "0.4"
49+
termcolor = "1.2.0"
4850
toml = "0.5"
4951
ignore = "0.4.10"
5052
opener = "0.5"

src/bootstrap/config.rs

+6
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ pub struct Config {
8787
pub patch_binaries_for_nix: bool,
8888
pub stage0_metadata: Stage0Metadata,
8989

90+
pub stdout_is_tty: bool,
91+
pub stderr_is_tty: bool,
92+
9093
pub on_fail: Option<String>,
9194
pub stage: u32,
9295
pub keep_stage: Vec<u32>,
@@ -825,6 +828,9 @@ impl Config {
825828
config.dist_include_mingw_linker = true;
826829
config.dist_compression_profile = "fast".into();
827830

831+
config.stdout_is_tty = atty::is(atty::Stream::Stdout);
832+
config.stderr_is_tty = atty::is(atty::Stream::Stderr);
833+
828834
// set by build.rs
829835
config.build = TargetSelection::from_user(&env!("BUILD_TRIPLE"));
830836

src/bootstrap/lib.rs

+27
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ mod format;
5555
mod install;
5656
mod metadata;
5757
mod native;
58+
mod render_tests;
5859
mod run;
5960
mod sanity;
6061
mod setup;
@@ -88,6 +89,7 @@ pub use crate::builder::PathSet;
8889
use crate::cache::{Interned, INTERNER};
8990
pub use crate::config::Config;
9091
pub use crate::flags::Subcommand;
92+
use termcolor::{ColorChoice, StandardStream, WriteColor};
9193

9294
const LLVM_TOOLS: &[&str] = &[
9395
"llvm-cov", // used to generate coverage report
@@ -1582,6 +1584,31 @@ to download LLVM rather than building it.
15821584

15831585
self.config.ninja_in_file
15841586
}
1587+
1588+
pub fn colored_stdout<R, F: FnOnce(&mut dyn WriteColor) -> R>(&self, f: F) -> R {
1589+
self.colored_stream_inner(StandardStream::stdout, self.config.stdout_is_tty, f)
1590+
}
1591+
1592+
pub fn colored_stderr<R, F: FnOnce(&mut dyn WriteColor) -> R>(&self, f: F) -> R {
1593+
self.colored_stream_inner(StandardStream::stderr, self.config.stderr_is_tty, f)
1594+
}
1595+
1596+
fn colored_stream_inner<R, F, C>(&self, constructor: C, is_tty: bool, f: F) -> R
1597+
where
1598+
C: Fn(ColorChoice) -> StandardStream,
1599+
F: FnOnce(&mut dyn WriteColor) -> R,
1600+
{
1601+
let choice = match self.config.color {
1602+
flags::Color::Always => ColorChoice::Always,
1603+
flags::Color::Never => ColorChoice::Never,
1604+
flags::Color::Auto if !is_tty => ColorChoice::Never,
1605+
flags::Color::Auto => ColorChoice::Auto,
1606+
};
1607+
let mut stream = constructor(choice);
1608+
let result = f(&mut stream);
1609+
stream.reset().unwrap();
1610+
result
1611+
}
15851612
}
15861613

15871614
#[cfg(unix)]

src/bootstrap/metrics.rs

+39-5
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ impl BuildMetrics {
5151
duration_excluding_children_sec: Duration::ZERO,
5252

5353
children: Vec::new(),
54+
tests: Vec::new(),
5455
});
5556
}
5657

@@ -72,6 +73,16 @@ impl BuildMetrics {
7273
}
7374
}
7475

76+
pub(crate) fn record_test(&self, name: &str, outcome: TestOutcome) {
77+
let mut state = self.state.borrow_mut();
78+
state
79+
.running_steps
80+
.last_mut()
81+
.unwrap()
82+
.tests
83+
.push(Test { name: name.to_string(), outcome });
84+
}
85+
7586
fn collect_stats(&self, state: &mut MetricsState) {
7687
let step = state.running_steps.last_mut().unwrap();
7788

@@ -125,6 +136,14 @@ impl BuildMetrics {
125136
}
126137

127138
fn prepare_json_step(&self, step: StepMetrics) -> JsonNode {
139+
let mut children = Vec::new();
140+
children.extend(step.children.into_iter().map(|child| self.prepare_json_step(child)));
141+
children.extend(
142+
step.tests
143+
.into_iter()
144+
.map(|test| JsonNode::Test { name: test.name, outcome: test.outcome }),
145+
);
146+
128147
JsonNode::RustbuildStep {
129148
type_: step.type_,
130149
debug_repr: step.debug_repr,
@@ -135,11 +154,7 @@ impl BuildMetrics {
135154
/ step.duration_excluding_children_sec.as_secs_f64(),
136155
},
137156

138-
children: step
139-
.children
140-
.into_iter()
141-
.map(|child| self.prepare_json_step(child))
142-
.collect(),
157+
children,
143158
}
144159
}
145160
}
@@ -161,6 +176,12 @@ struct StepMetrics {
161176
duration_excluding_children_sec: Duration,
162177

163178
children: Vec<StepMetrics>,
179+
tests: Vec<Test>,
180+
}
181+
182+
struct Test {
183+
name: String,
184+
outcome: TestOutcome,
164185
}
165186

166187
#[derive(Serialize, Deserialize)]
@@ -190,6 +211,19 @@ enum JsonNode {
190211

191212
children: Vec<JsonNode>,
192213
},
214+
Test {
215+
name: String,
216+
#[serde(flatten)]
217+
outcome: TestOutcome,
218+
},
219+
}
220+
221+
#[derive(Serialize, Deserialize)]
222+
#[serde(tag = "outcome", rename_all = "snake_case")]
223+
pub(crate) enum TestOutcome {
224+
Passed,
225+
Failed,
226+
Ignored { ignore_reason: Option<String> },
193227
}
194228

195229
#[derive(Serialize, Deserialize)]

0 commit comments

Comments
 (0)