Skip to content

Commit 8fff862

Browse files
committed
change tracker
1 parent ed7e93d commit 8fff862

13 files changed

Lines changed: 82 additions & 31 deletions

File tree

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

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::collections::HashSet;
1+
use std::collections::BTreeSet;
22
use std::fs::{self, File};
33
use std::io::{BufRead, BufReader, ErrorKind};
44
use std::path::{Path, PathBuf};
@@ -17,8 +17,16 @@ impl RecordFailedTests {
1717
}
1818
}
1919

20-
impl RecordFailedTests {}
21-
20+
/// This step is run as a dependency of most testing steps.
21+
/// Upon running, a file is created for failed tests to be recorded in if `--record` is passed on
22+
/// the command line.
23+
///
24+
/// This step is the only way to get access to a token type called [`RecordFailedTests`].
25+
/// Having this token type signifies the fact that a file was created to store failed tests in,
26+
/// and is required to create a `Renderer`, the type that renders the outputs of tests.
27+
///
28+
/// If `--rerun` isn't passed, or we're in dry-run mode, running this step is a no-op,
29+
/// and the `RecordFailedTest` type doesn't (need to) signify anything.
2230
#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
2331
pub struct SetupFailedTestsFile;
2432
impl Step for SetupFailedTestsFile {
@@ -46,7 +54,9 @@ impl Step for SetupFailedTestsFile {
4654
}
4755
}
4856

49-
pub fn collect_previously_failed_tests(failed_tests_file_path: &PathBuf, paths: &mut Vec<PathBuf>) {
57+
pub fn collect_previously_failed_tests(failed_tests_file_path: &PathBuf) -> Vec<PathBuf> {
58+
let mut paths = BTreeSet::new();
59+
5060
println!(
5161
"`--rerun` passed so looking for failed tests in {}",
5262
failed_tests_file_path.display()
@@ -58,45 +68,43 @@ pub fn collect_previously_failed_tests(failed_tests_file_path: &PathBuf, paths:
5868
println!(
5969
"WARNING: failed tests file doesn't exist: `--rerun` only makes sense after a previous test run with `--record`"
6070
);
61-
return;
71+
return Vec::new();
6272
}
6373
Err(e) => t!(Err(e)),
6474
};
6575

66-
let mut set_tracking_duplicates = HashSet::new();
67-
let mut num_printed = 0;
6876
const MAX_RERUN_PRINTS: usize = 10;
6977

7078
for line in lines {
7179
let trimmed = line.as_str().trim();
7280
let without_revision =
73-
trimmed.rsplit_once("#").map(|(before, _)| before).unwrap_or(&trimmed);
81+
trimmed.rsplit_once("#").map(|(before, _)| before).unwrap_or(trimmed);
7482
let without_suite_prefix = without_revision
7583
.strip_prefix("[")
7684
.and_then(|rest| rest.split_once("]"))
7785
.map(|(_, after)| after.trim())
7886
.unwrap_or(without_revision);
7987

8088
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:");
89+
if paths.insert(failed_test_path.clone()) {
90+
if paths.len() == 1 {
91+
println!("rerunning previously failed tests:");
8492
}
85-
if num_printed < MAX_RERUN_PRINTS {
93+
if paths.len() <= MAX_RERUN_PRINTS {
8694
println!(" {}", failed_test_path.display());
87-
num_printed += 1;
8895
}
89-
paths.push(failed_test_path);
9096
}
9197
}
9298

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)
99+
if paths.len() > MAX_RERUN_PRINTS {
100+
println!(" and {} more...", paths.len() - MAX_RERUN_PRINTS)
95101
}
96102

97-
if set_tracking_duplicates.is_empty() {
103+
if paths.is_empty() {
98104
println!(
99105
"WARNING: failed tests file doesn't contain any failed tests: `--rerun` only makes sense after a previous test run with `--record`"
100106
);
101107
}
108+
109+
paths.into_iter().collect()
102110
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1314,7 +1314,7 @@ impl Config {
13141314
let paths = {
13151315
let mut paths = Vec::new();
13161316
if flags_cmd.rerun() {
1317-
collect_previously_failed_tests(&record_failed_tests_path, &mut paths);
1317+
paths = collect_previously_failed_tests(&record_failed_tests_path);
13181318
} else {
13191319
paths.extend(flags_paths);
13201320
}

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,13 +441,13 @@ pub enum Subcommand {
441441
#[doc(hidden)]
442442
no_doc: bool,
443443

444-
#[arg(long)]
445444
/// Record all the failed tests in a file in the build directory.
446445
///
447446
/// On subsequent invocations, this set of tests can be rerun by passing `--rerun`
448-
record: bool,
449447
#[arg(long)]
448+
record: bool,
450449
/// Rerun tests that previously failed, and stored with `--record`.
450+
#[arg(long)]
451451
rerun: bool,
452452
},
453453
/// Build and run some test suites *in Miri*
@@ -739,6 +739,13 @@ impl Subcommand {
739739
_ => false,
740740
}
741741
}
742+
743+
pub fn rerun(&self) -> bool {
744+
match self {
745+
Subcommand::Test { rerun, .. } => *rerun,
746+
_ => false,
747+
}
748+
}
742749
}
743750

744751
/// Returns the shell completion for a given shell, if the result differs from the current

src/bootstrap/src/utils/change_tracker.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,11 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
621621
severity: ChangeSeverity::Info,
622622
summary: "`x.py` stopped accepting partial argument names. Use full names to avoid errors.",
623623
},
624+
ChangeInfo {
625+
change_id: 154586,
626+
severity: ChangeSeverity::Info,
627+
summary: "New option `build.record_failed_tests_path` to store failed tests when passing `--record`. These can be rerun with `--rerun`.",
628+
},
624629
ChangeInfo {
625630
change_id: 154587,
626631
severity: ChangeSeverity::Info,

src/bootstrap/src/utils/render_tests.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ impl<'a> Renderer<'a> {
109109
) -> Self {
110110
let failed_tests = record_failed_tests.path().and_then(|path| {
111111
// create the file (overwriting any previous) to get ready to record new failed tests
112-
match File::options().create(true).append(true).truncate(false).open(&path) {
112+
match File::options().create(true).append(true).truncate(false).open(path) {
113113
Ok(f) => Some(f),
114114
Err(e) => {
115115
println!(
@@ -299,6 +299,13 @@ impl<'a> Renderer<'a> {
299299
for failure in &self.failures {
300300
println!(" {}", failure.name);
301301
}
302+
303+
if self.failed_tests.is_some() {
304+
println!(
305+
"This list of test failures was recorded.\nUse `x test --rerun` to retry just these {} failed tests.",
306+
self.failures.len(),
307+
)
308+
}
302309
}
303310

304311
if !self.benches.is_empty() {
@@ -391,12 +398,12 @@ impl<'a> Renderer<'a> {
391398
}
392399
Message::Test(TestMessage::Failed(outcome)) => {
393400
self.render_test_outcome(Outcome::Failed, &outcome);
394-
if let Some(failed_tests) = &mut self.failed_tests {
395-
if let Err(e) = writeln!(failed_tests, "{}", outcome.name) {
396-
eprintln!(
397-
"failed to write test failure to file: {e} (attempted because `--record` was passed)"
398-
);
399-
}
401+
if let Some(failed_tests) = &mut self.failed_tests
402+
&& let Err(e) = writeln!(failed_tests, "{}", outcome.name)
403+
{
404+
eprintln!(
405+
"failed to write test failure to file: {e} (attempted because `--record` was passed)"
406+
);
400407
}
401408
self.failures.push(outcome);
402409
}

src/etc/completions/x.fish

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,8 @@ complete -c x -n "__fish_x_using_subcommand test" -l rustfix-coverage -d 'enable
465465
complete -c x -n "__fish_x_using_subcommand test" -l no-capture -d 'don\'t capture stdout/stderr of tests'
466466
complete -c x -n "__fish_x_using_subcommand test" -l bypass-ignore-backends -d 'Ignore `//@ ignore-backends` directives'
467467
complete -c x -n "__fish_x_using_subcommand test" -l no-doc -d 'Deprecated. Use `--all-targets` or `--tests` instead'
468+
complete -c x -n "__fish_x_using_subcommand test" -l record -d 'Record all the failed tests in a file in the build directory'
469+
complete -c x -n "__fish_x_using_subcommand test" -l rerun -d 'Rerun tests that previously failed, and stored with `--record`'
468470
complete -c x -n "__fish_x_using_subcommand test" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
469471
complete -c x -n "__fish_x_using_subcommand test" -s q -l quiet -d 'use quiet output'
470472
complete -c x -n "__fish_x_using_subcommand test" -s i -l incremental -d 'use incremental compilation'
@@ -520,6 +522,8 @@ complete -c x -n "__fish_x_using_subcommand t" -l rustfix-coverage -d 'enable th
520522
complete -c x -n "__fish_x_using_subcommand t" -l no-capture -d 'don\'t capture stdout/stderr of tests'
521523
complete -c x -n "__fish_x_using_subcommand t" -l bypass-ignore-backends -d 'Ignore `//@ ignore-backends` directives'
522524
complete -c x -n "__fish_x_using_subcommand t" -l no-doc -d 'Deprecated. Use `--all-targets` or `--tests` instead'
525+
complete -c x -n "__fish_x_using_subcommand t" -l record -d 'Record all the failed tests in a file in the build directory'
526+
complete -c x -n "__fish_x_using_subcommand t" -l rerun -d 'Rerun tests that previously failed, and stored with `--record`'
523527
complete -c x -n "__fish_x_using_subcommand t" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
524528
complete -c x -n "__fish_x_using_subcommand t" -s q -l quiet -d 'use quiet output'
525529
complete -c x -n "__fish_x_using_subcommand t" -s i -l incremental -d 'use incremental compilation'

src/etc/completions/x.ps1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock {
543543
[CompletionResult]::new('--no-capture', '--no-capture', [CompletionResultType]::ParameterName, 'don''t capture stdout/stderr of tests')
544544
[CompletionResult]::new('--bypass-ignore-backends', '--bypass-ignore-backends', [CompletionResultType]::ParameterName, 'Ignore `//@ ignore-backends` directives')
545545
[CompletionResult]::new('--no-doc', '--no-doc', [CompletionResultType]::ParameterName, 'Deprecated. Use `--all-targets` or `--tests` instead')
546+
[CompletionResult]::new('--record', '--record', [CompletionResultType]::ParameterName, 'Record all the failed tests in a file in the build directory')
547+
[CompletionResult]::new('--rerun', '--rerun', [CompletionResultType]::ParameterName, 'Rerun tests that previously failed, and stored with `--record`')
546548
[CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
547549
[CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
548550
[CompletionResult]::new('-q', '-q', [CompletionResultType]::ParameterName, 'use quiet output')
@@ -606,6 +608,8 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock {
606608
[CompletionResult]::new('--no-capture', '--no-capture', [CompletionResultType]::ParameterName, 'don''t capture stdout/stderr of tests')
607609
[CompletionResult]::new('--bypass-ignore-backends', '--bypass-ignore-backends', [CompletionResultType]::ParameterName, 'Ignore `//@ ignore-backends` directives')
608610
[CompletionResult]::new('--no-doc', '--no-doc', [CompletionResultType]::ParameterName, 'Deprecated. Use `--all-targets` or `--tests` instead')
611+
[CompletionResult]::new('--record', '--record', [CompletionResultType]::ParameterName, 'Record all the failed tests in a file in the build directory')
612+
[CompletionResult]::new('--rerun', '--rerun', [CompletionResultType]::ParameterName, 'Rerun tests that previously failed, and stored with `--record`')
609613
[CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
610614
[CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
611615
[CompletionResult]::new('-q', '-q', [CompletionResultType]::ParameterName, 'use quiet output')

src/etc/completions/x.py.fish

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand test" -l rustfix-coverage -d '
465465
complete -c x.py -n "__fish_x.py_using_subcommand test" -l no-capture -d 'don\'t capture stdout/stderr of tests'
466466
complete -c x.py -n "__fish_x.py_using_subcommand test" -l bypass-ignore-backends -d 'Ignore `//@ ignore-backends` directives'
467467
complete -c x.py -n "__fish_x.py_using_subcommand test" -l no-doc -d 'Deprecated. Use `--all-targets` or `--tests` instead'
468+
complete -c x.py -n "__fish_x.py_using_subcommand test" -l record -d 'Record all the failed tests in a file in the build directory'
469+
complete -c x.py -n "__fish_x.py_using_subcommand test" -l rerun -d 'Rerun tests that previously failed, and stored with `--record`'
468470
complete -c x.py -n "__fish_x.py_using_subcommand test" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
469471
complete -c x.py -n "__fish_x.py_using_subcommand test" -s q -l quiet -d 'use quiet output'
470472
complete -c x.py -n "__fish_x.py_using_subcommand test" -s i -l incremental -d 'use incremental compilation'
@@ -520,6 +522,8 @@ complete -c x.py -n "__fish_x.py_using_subcommand t" -l rustfix-coverage -d 'ena
520522
complete -c x.py -n "__fish_x.py_using_subcommand t" -l no-capture -d 'don\'t capture stdout/stderr of tests'
521523
complete -c x.py -n "__fish_x.py_using_subcommand t" -l bypass-ignore-backends -d 'Ignore `//@ ignore-backends` directives'
522524
complete -c x.py -n "__fish_x.py_using_subcommand t" -l no-doc -d 'Deprecated. Use `--all-targets` or `--tests` instead'
525+
complete -c x.py -n "__fish_x.py_using_subcommand t" -l record -d 'Record all the failed tests in a file in the build directory'
526+
complete -c x.py -n "__fish_x.py_using_subcommand t" -l rerun -d 'Rerun tests that previously failed, and stored with `--record`'
523527
complete -c x.py -n "__fish_x.py_using_subcommand t" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
524528
complete -c x.py -n "__fish_x.py_using_subcommand t" -s q -l quiet -d 'use quiet output'
525529
complete -c x.py -n "__fish_x.py_using_subcommand t" -s i -l incremental -d 'use incremental compilation'

src/etc/completions/x.py.ps1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
543543
[CompletionResult]::new('--no-capture', '--no-capture', [CompletionResultType]::ParameterName, 'don''t capture stdout/stderr of tests')
544544
[CompletionResult]::new('--bypass-ignore-backends', '--bypass-ignore-backends', [CompletionResultType]::ParameterName, 'Ignore `//@ ignore-backends` directives')
545545
[CompletionResult]::new('--no-doc', '--no-doc', [CompletionResultType]::ParameterName, 'Deprecated. Use `--all-targets` or `--tests` instead')
546+
[CompletionResult]::new('--record', '--record', [CompletionResultType]::ParameterName, 'Record all the failed tests in a file in the build directory')
547+
[CompletionResult]::new('--rerun', '--rerun', [CompletionResultType]::ParameterName, 'Rerun tests that previously failed, and stored with `--record`')
546548
[CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
547549
[CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
548550
[CompletionResult]::new('-q', '-q', [CompletionResultType]::ParameterName, 'use quiet output')
@@ -606,6 +608,8 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
606608
[CompletionResult]::new('--no-capture', '--no-capture', [CompletionResultType]::ParameterName, 'don''t capture stdout/stderr of tests')
607609
[CompletionResult]::new('--bypass-ignore-backends', '--bypass-ignore-backends', [CompletionResultType]::ParameterName, 'Ignore `//@ ignore-backends` directives')
608610
[CompletionResult]::new('--no-doc', '--no-doc', [CompletionResultType]::ParameterName, 'Deprecated. Use `--all-targets` or `--tests` instead')
611+
[CompletionResult]::new('--record', '--record', [CompletionResultType]::ParameterName, 'Record all the failed tests in a file in the build directory')
612+
[CompletionResult]::new('--rerun', '--rerun', [CompletionResultType]::ParameterName, 'Rerun tests that previously failed, and stored with `--record`')
609613
[CompletionResult]::new('-v', '-v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
610614
[CompletionResult]::new('--verbose', '--verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
611615
[CompletionResult]::new('-q', '-q', [CompletionResultType]::ParameterName, 'use quiet output')

0 commit comments

Comments
 (0)