Skip to content

Commit d4868b8

Browse files
committed
rerun failed tests
rerun failed tests
1 parent 7c79bb9 commit d4868b8

3 files changed

Lines changed: 78 additions & 9 deletions

File tree

src/bootstrap/src/core/build_steps/test/failed_tests.rs

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use std::fs;
1+
use std::collections::HashSet;
2+
use std::fs::{self, File};
3+
use std::io::{BufRead, BufReader, ErrorKind};
24
use std::path::{Path, PathBuf};
35

46
use crate::core::builder::{Builder, ShouldRun, Step};
@@ -31,9 +33,9 @@ impl Step for SetupFailedTestsFile {
3133
return RecordFailedTests { failed_tests_path: None };
3234
}
3335

34-
let failed_tests_path = builder.out.join(&builder.config.record_failed_tests_path);
36+
let failed_tests_path = builder.config.record_failed_tests_path.clone();
3537
println!(
36-
"setting up tracking of failed tests in {} (--record was passed)",
38+
"setting up tracking of failed tests in {} (`--record` was passed)",
3739
failed_tests_path.display()
3840
);
3941
if failed_tests_path.exists() {
@@ -43,3 +45,58 @@ impl Step for SetupFailedTestsFile {
4345
RecordFailedTests { failed_tests_path: Some(failed_tests_path) }
4446
}
4547
}
48+
49+
pub fn collect_previously_failed_tests(failed_tests_file_path: &PathBuf, paths: &mut Vec<PathBuf>) {
50+
println!(
51+
"`--rerun` passed so looking for failed tests in {}",
52+
failed_tests_file_path.display()
53+
);
54+
55+
let lines: Vec<String> = match File::open(failed_tests_file_path) {
56+
Ok(f) => t!(BufReader::new(f).lines().collect()),
57+
Err(e) if e.kind() == ErrorKind::NotFound => {
58+
println!(
59+
"WARNING: failed tests file doesn't exist: `--rerun` only makes sense after a previous test run with `--record`"
60+
);
61+
return;
62+
}
63+
Err(e) => t!(Err(e)),
64+
};
65+
66+
let mut set_tracking_duplicates = HashSet::new();
67+
let mut num_printed = 0;
68+
const MAX_RERUN_PRINTS: usize = 10;
69+
70+
for line in lines {
71+
let trimmed = line.as_str().trim();
72+
let without_revision =
73+
trimmed.rsplit_once("#").map(|(before, _)| before).unwrap_or(&trimmed);
74+
let without_suite_prefix = without_revision
75+
.strip_prefix("[")
76+
.and_then(|rest| rest.split_once("]"))
77+
.map(|(_, after)| after.trim())
78+
.unwrap_or(without_revision);
79+
80+
let failed_test_path = PathBuf::from(without_suite_prefix.to_string());
81+
if set_tracking_duplicates.insert(failed_test_path.clone()) {
82+
if num_printed == 0 {
83+
println!("rerunning previousy failed tests:");
84+
}
85+
if num_printed < MAX_RERUN_PRINTS {
86+
println!(" {}", failed_test_path.display());
87+
num_printed += 1;
88+
}
89+
paths.push(failed_test_path);
90+
}
91+
}
92+
93+
if num_printed == MAX_RERUN_PRINTS && set_tracking_duplicates.len() > MAX_RERUN_PRINTS {
94+
println!(" and {} more...", set_tracking_duplicates.len() - MAX_RERUN_PRINTS)
95+
}
96+
97+
if set_tracking_duplicates.is_empty() {
98+
println!(
99+
"WARNING: failed tests file doesn't contain any failed tests: `--rerun` only makes sense after a previous test run with `--record`"
100+
);
101+
}
102+
}

src/bootstrap/src/core/config/config.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use tracing::{instrument, span};
3030

3131
use crate::core::build_steps::llvm;
3232
use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
33+
use crate::core::build_steps::test::failed_tests::collect_previously_failed_tests;
3334
pub use crate::core::config::flags::Subcommand;
3435
use crate::core::config::flags::{Color, Flags, Warnings};
3536
use crate::core::config::target_selection::TargetSelectionList;
@@ -1307,6 +1308,19 @@ impl Config {
13071308
);
13081309
let verbose_tests = rust_verbose_tests.unwrap_or(exec_ctx.is_verbose());
13091310

1311+
let record_failed_tests_path =
1312+
out.join(build_record_failed_tests_path.unwrap_or_else(|| "failed-tests".to_string()));
1313+
1314+
let paths = {
1315+
let mut paths = Vec::new();
1316+
if flags_cmd.rerun() {
1317+
collect_previously_failed_tests(&record_failed_tests_path, &mut paths);
1318+
} else {
1319+
paths.extend(flags_paths);
1320+
}
1321+
paths
1322+
};
1323+
13101324
Config {
13111325
// tidy-alphabetical-start
13121326
android_ndk: build_android_ndk,
@@ -1437,16 +1451,14 @@ impl Config {
14371451
out,
14381452
patch_binaries_for_nix: build_patch_binaries_for_nix,
14391453
path_modification_cache,
1440-
paths: flags_paths,
1454+
paths,
14411455
prefix: install_prefix.map(PathBuf::from),
14421456
print_step_rusage: build_print_step_rusage.unwrap_or(false),
14431457
print_step_timings: build_print_step_timings.unwrap_or(false),
14441458
profiler: build_profiler.unwrap_or(false),
14451459
python: build_python.map(PathBuf::from),
14461460
quiet: flags_quiet,
1447-
record_failed_tests_path: build_record_failed_tests_path
1448-
.unwrap_or_else(|| "failed-tests".to_string())
1449-
.into(),
1461+
record_failed_tests_path,
14501462
reproducible_artifacts: flags_reproducible_artifact,
14511463
reuse: build_reuse.map(PathBuf::from),
14521464
rust_analyzer_info,

src/bootstrap/src/utils/render_tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ impl<'a> Renderer<'a> {
113113
Ok(f) => Some(f),
114114
Err(e) => {
115115
println!(
116-
"Couldn't open file {} to write test failutes to: {e}. (attempted because --record was passed). Test failures will not be recorded.",
116+
"Couldn't open file {} to write test failutes to: {e}. (attempted because `--record` was passed). Test failures will not be recorded.",
117117
path.display()
118118
);
119119
None
@@ -394,7 +394,7 @@ impl<'a> Renderer<'a> {
394394
if let Some(failed_tests) = &mut self.failed_tests {
395395
if let Err(e) = writeln!(failed_tests, "{}", outcome.name) {
396396
eprintln!(
397-
"failed to write test failure to file: {e} (attempted because --record was passed)"
397+
"failed to write test failure to file: {e} (attempted because `--record` was passed)"
398398
);
399399
}
400400
}

0 commit comments

Comments
 (0)