Skip to content

Commit b22e2bb

Browse files
authored
Merge pull request #262 from oli-obk/ctrlc
Stop tests early when Ctrl+C is pressed
2 parents a4dc487 + 9c0ae89 commit b22e2bb

File tree

20 files changed

+298
-135
lines changed

20 files changed

+298
-135
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717
### Changed
1818

1919
* default comment symbols for `Config::cargo` changed to `#`
20+
* Ctrl+C now prints the summary of the tests that were run before Ctrl+C is pressed
2021

2122
### Removed
2223

Cargo.lock

Lines changed: 70 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ annotate-snippets = { version = "0.11.2" }
3030
levenshtein = "1.0.5"
3131
spanned = "0.3.0"
3232

33+
[dev-dependencies]
34+
ctrlc = "3.4.5"
35+
3336
[dependencies.regex]
3437
version = "1.5.5"
3538
default-features = false

examples/rustc_basic.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1+
use std::sync::atomic::Ordering;
12
use ui_test::{run_tests, Config};
23

34
fn main() -> ui_test::color_eyre::Result<()> {
5+
let config = Config::rustc("examples_tests/rustc_basic");
6+
let abort_check = config.abort_check.clone();
7+
ctrlc::set_handler(move || abort_check.store(true, Ordering::Relaxed))?;
8+
49
// Compile all `.rs` files in the given directory (relative to your
510
// Cargo.toml) and compare their output against the corresponding
611
// `.stderr` files.
7-
run_tests(Config::rustc("examples_tests/rustc_basic"))
12+
run_tests(config)
813
}

src/aux_builds.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ impl Build for AuxBuilder {
140140
// Now run the command again to fetch the output filenames
141141
aux_cmd.arg("--print").arg("file-names");
142142
let output = aux_cmd.output().unwrap();
143+
144+
if build_manager.aborted() {
145+
return Err(Errored::aborted());
146+
}
147+
143148
assert!(output.status.success());
144149

145150
let mut extra_args = vec![];

src/build_manager.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ pub struct BuildManager {
3333
new_job_submitter: Sender<NewJob>,
3434
}
3535

36-
type NewJob = Box<dyn Send + for<'a> FnOnce(&'a Sender<TestRun>) -> Result<()>>;
36+
/// Type of closure that is used to run individual tests.
37+
pub type NewJob = Box<dyn Send + for<'a> FnOnce(&'a Sender<TestRun>) -> Result<()>>;
3738

3839
impl BuildManager {
3940
/// Create a new `BuildManager` for a specific `Config`. Each `Config` needs
@@ -49,6 +50,9 @@ impl BuildManager {
4950
/// Lazily add more jobs after a test has finished. These are added to the queue
5051
/// as normally, but nested below the test.
5152
pub fn add_new_job(&self, job: impl Send + 'static + FnOnce() -> TestRun) {
53+
if self.aborted() {
54+
return;
55+
}
5256
self.new_job_submitter
5357
.send(Box::new(move |sender| Ok(sender.send(job())?)))
5458
.unwrap()
@@ -114,6 +118,7 @@ impl BuildManager {
114118
stderr: vec![],
115119
stdout: vec![],
116120
}),
121+
self.aborted(),
117122
);
118123
res
119124
})
@@ -132,4 +137,9 @@ impl BuildManager {
132137
pub fn config(&self) -> &Config {
133138
&self.config
134139
}
140+
141+
/// Whether the build was cancelled
142+
pub fn aborted(&self) -> bool {
143+
self.config.aborted()
144+
}
135145
}

src/config.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use std::{
2020
collections::BTreeMap,
2121
num::NonZeroUsize,
2222
path::{Path, PathBuf},
23+
sync::{atomic::AtomicBool, Arc},
2324
};
2425

2526
mod args;
@@ -63,6 +64,10 @@ pub struct Config {
6364
pub custom_comments: BTreeMap<&'static str, CommandParserFunc>,
6465
/// Custom diagnostic extractor (invoked on the output of tests)
6566
pub diagnostic_extractor: fn(&Path, &[u8]) -> Diagnostics,
67+
/// An atomic bool that can be set to `true` to abort all tests.
68+
/// Will not cancel child processes, but if set from a Ctrl+C handler,
69+
/// the pressing of Ctrl+C will already have cancelled child processes.
70+
pub abort_check: Arc<AtomicBool>,
6671
}
6772

6873
impl Config {
@@ -157,6 +162,7 @@ impl Config {
157162
comment_start: "//",
158163
custom_comments: Default::default(),
159164
diagnostic_extractor: rustc_stderr::process,
165+
abort_check: Default::default(),
160166
};
161167
config
162168
.custom_comments
@@ -409,6 +415,10 @@ impl Config {
409415
.all(|c| self.test_condition(c))
410416
^ self.run_only_ignored
411417
}
418+
419+
pub(crate) fn aborted(&self) -> bool {
420+
self.abort_check.load(std::sync::atomic::Ordering::Relaxed)
421+
}
412422
}
413423

414424
#[derive(Debug, Clone)]

src/custom_flags/run.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ impl Flag for Run {
4242
build_manager.add_new_job(move || {
4343
cmd.arg("--print").arg("file-names");
4444
let output = cmd.output().unwrap();
45+
if config.aborted() {
46+
return TestRun {
47+
result: Err(Errored::aborted()),
48+
status: config.status,
49+
abort_check: config.config.abort_check.clone(),
50+
};
51+
}
4552
assert!(output.status.success(), "{cmd:#?}: {output:#?}");
4653

4754
let mut files = output.stdout.lines();
@@ -61,6 +68,14 @@ impl Flag for Run {
6168
.output()
6269
.unwrap_or_else(|err| panic!("exe file: {}: {err}", display(&exe_file)));
6370

71+
if config.aborted() {
72+
return TestRun {
73+
result: Err(Errored::aborted()),
74+
status: config.status,
75+
abort_check: config.config.abort_check.clone(),
76+
};
77+
}
78+
6479
let mut errors = vec![];
6580

6681
config.check_test_output(&mut errors, &output.stdout, &output.stderr);
@@ -93,6 +108,7 @@ impl Flag for Run {
93108
})
94109
},
95110
status: config.status,
111+
abort_check: config.config.abort_check,
96112
}
97113
});
98114
Ok(())

src/custom_flags/rustfix.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,9 @@ fn compile_fixed(
219219
.arg(format!("{crate_name}_________{}", i + 1));
220220
build_manager.add_new_job(move || {
221221
let output = cmd.output().unwrap();
222-
let result = if output.status.success() {
222+
let result = if fixed_config.aborted() {
223+
Err(Errored::aborted())
224+
} else if output.status.success() {
223225
Ok(TestOk::Ok)
224226
} else {
225227
let diagnostics = fixed_config.process(&output.stderr);
@@ -247,6 +249,7 @@ fn compile_fixed(
247249
TestRun {
248250
result,
249251
status: fixed_config.status,
252+
abort_check: fixed_config.config.abort_check,
250253
}
251254
});
252255
}

0 commit comments

Comments
 (0)