Skip to content

Commit 52e4919

Browse files
committed
Only spawn subprocesses when panic=abort
1 parent 78ff110 commit 52e4919

File tree

3 files changed

+73
-38
lines changed

3 files changed

+73
-38
lines changed

src/librustc_interface/passes.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ fn configure_and_expand_inner<'a>(
446446
&mut krate,
447447
sess.diagnostic(),
448448
&sess.features_untracked(),
449+
sess.panic_strategy(),
449450
)
450451
});
451452

src/libsyntax_ext/test_harness.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
use log::debug;
44
use smallvec::{smallvec, SmallVec};
5+
use rustc_target::spec::PanicStrategy;
56
use syntax::ast::{self, Ident};
67
use syntax::attr;
78
use syntax::entry::{self, EntryPointType};
@@ -25,6 +26,7 @@ struct Test {
2526

2627
struct TestCtxt<'a> {
2728
ext_cx: ExtCtxt<'a>,
29+
panic_strategy: PanicStrategy,
2830
def_site: Span,
2931
test_cases: Vec<Test>,
3032
reexport_test_harness_main: Option<Symbol>,
@@ -40,6 +42,7 @@ pub fn inject(
4042
krate: &mut ast::Crate,
4143
span_diagnostic: &errors::Handler,
4244
features: &Features,
45+
panic_strategy: PanicStrategy,
4346
) {
4447
// Check for #![reexport_test_harness_main = "some_name"] which gives the
4548
// main test function the name `some_name` without hygiene. This needs to be
@@ -54,7 +57,7 @@ pub fn inject(
5457

5558
if should_test {
5659
generate_test_harness(sess, resolver, reexport_test_harness_main,
57-
krate, features, test_runner)
60+
krate, features, panic_strategy, test_runner)
5861
}
5962
}
6063

@@ -183,6 +186,7 @@ fn generate_test_harness(sess: &ParseSess,
183186
reexport_test_harness_main: Option<Symbol>,
184187
krate: &mut ast::Crate,
185188
features: &Features,
189+
panic_strategy: PanicStrategy,
186190
test_runner: Option<ast::Path>) {
187191
let mut econfig = ExpansionConfig::default("test".to_string());
188192
econfig.features = Some(features);
@@ -203,6 +207,7 @@ fn generate_test_harness(sess: &ParseSess,
203207

204208
let cx = TestCtxt {
205209
ext_cx,
210+
panic_strategy,
206211
def_site,
207212
test_cases: Vec::new(),
208213
reexport_test_harness_main,
@@ -248,9 +253,14 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
248253
let ecx = &cx.ext_cx;
249254
let test_id = Ident::new(sym::test, sp);
250255

256+
let runner_name = match cx.panic_strategy {
257+
PanicStrategy::Unwind => "test_main_static",
258+
PanicStrategy::Abort => "test_main_static_abort",
259+
};
260+
251261
// test::test_main_static(...)
252262
let mut test_runner = cx.test_runner.clone().unwrap_or(
253-
ecx.path(sp, vec![test_id, ecx.ident_of("test_main_static", sp)]));
263+
ecx.path(sp, vec![test_id, ecx.ident_of(runner_name, sp)]));
254264

255265
test_runner.span = sp;
256266

src/libtest/lib.rs

Lines changed: 60 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -261,37 +261,31 @@ impl Metric {
261261
#[derive(Copy, Clone, Debug)]
262262
pub struct Options {
263263
display_output: bool,
264+
panic_abort: bool,
264265
}
265266

266267
impl Options {
267268
pub fn new() -> Options {
268269
Options {
269270
display_output: false,
271+
panic_abort: false,
270272
}
271273
}
272274

273275
pub fn display_output(mut self, display_output: bool) -> Options {
274276
self.display_output = display_output;
275277
self
276278
}
279+
280+
pub fn panic_abort(mut self, panic_abort: bool) -> Options {
281+
self.panic_abort = panic_abort;
282+
self
283+
}
277284
}
278285

279286
// The default console test runner. It accepts the command line
280287
// arguments and a vector of test_descs.
281288
pub fn test_main(args: &[String], tests: Vec<TestDescAndFn>, options: Option<Options>) {
282-
// If we're being run in SpawnedSecondary mode, run the test here. run_test
283-
// will then exit the process.
284-
if let Ok(name) = env::var(SECONDARY_TEST_INVOKER_VAR) {
285-
let test = tests
286-
.into_iter()
287-
.filter(|test| test.desc.name.as_slice() == name)
288-
.next()
289-
.expect("couldn't find a test with the provided name");
290-
let opts = parse_opts(&[]).unwrap().unwrap();
291-
run_test(&opts, false, test, RunStrategy::SpawnedSecondary, Concurrent::No);
292-
unreachable!();
293-
}
294-
295289
let mut opts = match parse_opts(args) {
296290
Some(Ok(o)) => o,
297291
Some(Err(msg)) => {
@@ -320,32 +314,63 @@ pub fn test_main(args: &[String], tests: Vec<TestDescAndFn>, options: Option<Opt
320314
}
321315
}
322316

323-
// A variant optimized for invocation with a static test vector.
324-
// This will panic (intentionally) when fed any dynamic tests, because
325-
// it is copying the static values out into a dynamic vector and cannot
326-
// copy dynamic values. It is doing this because from this point on
327-
// a Vec<TestDescAndFn> is used in order to effect ownership-transfer
328-
// semantics into parallel test runners, which in turn requires a Vec<>
329-
// rather than a &[].
317+
/// A variant optimized for invocation with a static test vector.
318+
/// This will panic (intentionally) when fed any dynamic tests.
319+
///
320+
/// This is the entry point for the main function generated by `rustc --test`
321+
/// when panic=unwind.
330322
pub fn test_main_static(tests: &[&TestDescAndFn]) {
331323
let args = env::args().collect::<Vec<_>>();
332-
let owned_tests = tests
333-
.iter()
334-
.map(|t| match t.testfn {
335-
StaticTestFn(f) => TestDescAndFn {
336-
testfn: StaticTestFn(f),
337-
desc: t.desc.clone(),
338-
},
339-
StaticBenchFn(f) => TestDescAndFn {
340-
testfn: StaticBenchFn(f),
341-
desc: t.desc.clone(),
342-
},
343-
_ => panic!("non-static tests passed to test::test_main_static"),
344-
})
345-
.collect();
324+
let owned_tests: Vec<_> = tests.iter().map(make_owned_test).collect();
346325
test_main(&args, owned_tests, None)
347326
}
348327

328+
/// A variant optimized for invocation with a static test vector.
329+
/// This will panic (intentionally) when fed any dynamic tests.
330+
///
331+
/// Runs tests in panic=abort mode, which involves spawning subprocesses for
332+
/// tests.
333+
///
334+
/// This is the entry point for the main function generated by `rustc --test`
335+
/// when panic=abort.
336+
pub fn test_main_static_abort(tests: &[&TestDescAndFn]) {
337+
// If we're being run in SpawnedSecondary mode, run the test here. run_test
338+
// will then exit the process.
339+
if let Ok(name) = env::var(SECONDARY_TEST_INVOKER_VAR) {
340+
let test = tests
341+
.iter()
342+
.filter(|test| test.desc.name.as_slice() == name)
343+
.map(make_owned_test)
344+
.next()
345+
.expect("couldn't find a test with the provided name");
346+
let opts = parse_opts(&[]).unwrap().unwrap();
347+
run_test(&opts, false, test, RunStrategy::SpawnedSecondary, Concurrent::No);
348+
unreachable!();
349+
}
350+
351+
let args = env::args().collect::<Vec<_>>();
352+
let owned_tests: Vec<_> = tests.iter().map(make_owned_test).collect();
353+
test_main(&args, owned_tests, Some(Options::new().panic_abort(true)))
354+
}
355+
356+
/// Clones static values for putting into a dynamic vector, which test_main()
357+
/// needs to hand out ownership of tests to parallel test runners.
358+
///
359+
/// This will panic when fed any dynamic tests, because they cannot be cloned.
360+
fn make_owned_test(test: &&TestDescAndFn) -> TestDescAndFn {
361+
match test.testfn {
362+
StaticTestFn(f) => TestDescAndFn {
363+
testfn: StaticTestFn(f),
364+
desc: test.desc.clone(),
365+
},
366+
StaticBenchFn(f) => TestDescAndFn {
367+
testfn: StaticBenchFn(f),
368+
desc: test.desc.clone(),
369+
},
370+
_ => panic!("non-static tests passed to test::test_main_static"),
371+
}
372+
}
373+
349374
/// Invoked when unit tests terminate. Should panic if the unit
350375
/// Tests is considered a failure. By default, invokes `report()`
351376
/// and checks for a `0` result.
@@ -1147,8 +1172,7 @@ where
11471172
let mut pending = 0;
11481173

11491174
let (tx, rx) = channel::<MonitorMsg>();
1150-
// TODO
1151-
let run_strategy = if true {
1175+
let run_strategy = if opts.options.panic_abort {
11521176
RunStrategy::SpawnPrimary(tx)
11531177
} else {
11541178
RunStrategy::InProcess(tx)

0 commit comments

Comments
 (0)