Skip to content

Commit b1d60bc

Browse files
committed
refactor executing tests to centralize actually invoking tests
Before this commit, tests were invoked in multiple places, especially due to `-Z panic-abort-tests`, and adding a new test kind meant having to chase down and update all these places. This commit creates a new Runnable enum, and its children RunnableTest and RunnableBench. The rest of the harness will now pass around the enum rather than constructing and passing around boxed functions. The enum has two children enums because invoking tests and invoking benchmarks requires different parameters.
1 parent 776f222 commit b1d60bc

File tree

2 files changed

+90
-41
lines changed

2 files changed

+90
-41
lines changed

library/test/src/lib.rs

Lines changed: 28 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,17 @@ pub fn test_main_static_abort(tests: &[&TestDescAndFn]) {
178178
.next()
179179
.unwrap_or_else(|| panic!("couldn't find a test with the provided name '{name}'"));
180180
let TestDescAndFn { desc, testfn } = test;
181-
let testfn = match testfn {
182-
StaticTestFn(f) => f,
183-
_ => panic!("only static tests are supported"),
184-
};
185-
run_test_in_spawned_subprocess(desc, Box::new(testfn));
181+
match testfn.into_runnable() {
182+
Runnable::Test(runnable_test) => {
183+
if runnable_test.is_dynamic() {
184+
panic!("only static tests are supported");
185+
}
186+
run_test_in_spawned_subprocess(desc, runnable_test);
187+
}
188+
Runnable::Bench(_) => {
189+
panic!("benchmarks should not be executed into child processes")
190+
}
191+
}
186192
}
187193

188194
let args = env::args().collect::<Vec<_>>();
@@ -563,7 +569,7 @@ pub fn run_test(
563569
id: TestId,
564570
desc: TestDesc,
565571
monitor_ch: Sender<CompletedTest>,
566-
testfn: Box<dyn FnOnce() -> Result<(), String> + Send>,
572+
runnable_test: RunnableTest,
567573
opts: TestRunOpts,
568574
) -> Option<thread::JoinHandle<()>> {
569575
let name = desc.name.clone();
@@ -574,7 +580,7 @@ pub fn run_test(
574580
desc,
575581
opts.nocapture,
576582
opts.time.is_some(),
577-
testfn,
583+
runnable_test,
578584
monitor_ch,
579585
opts.time,
580586
),
@@ -615,37 +621,21 @@ pub fn run_test(
615621
let test_run_opts =
616622
TestRunOpts { strategy, nocapture: opts.nocapture, time: opts.time_options };
617623

618-
match testfn {
619-
DynBenchFn(benchfn) => {
620-
// Benchmarks aren't expected to panic, so we run them all in-process.
621-
crate::bench::benchmark(id, desc, monitor_ch, opts.nocapture, benchfn);
622-
None
624+
match testfn.into_runnable() {
625+
Runnable::Test(runnable_test) => {
626+
if runnable_test.is_dynamic() {
627+
match strategy {
628+
RunStrategy::InProcess => (),
629+
_ => panic!("Cannot run dynamic test fn out-of-process"),
630+
};
631+
}
632+
run_test_inner(id, desc, monitor_ch, runnable_test, test_run_opts)
623633
}
624-
StaticBenchFn(benchfn) => {
634+
Runnable::Bench(runnable_bench) => {
625635
// Benchmarks aren't expected to panic, so we run them all in-process.
626-
crate::bench::benchmark(id, desc, monitor_ch, opts.nocapture, benchfn);
636+
runnable_bench.run(id, &desc, &monitor_ch, opts.nocapture);
627637
None
628638
}
629-
DynTestFn(f) => {
630-
match strategy {
631-
RunStrategy::InProcess => (),
632-
_ => panic!("Cannot run dynamic test fn out-of-process"),
633-
};
634-
run_test_inner(
635-
id,
636-
desc,
637-
monitor_ch,
638-
Box::new(move || __rust_begin_short_backtrace(f)),
639-
test_run_opts,
640-
)
641-
}
642-
StaticTestFn(f) => run_test_inner(
643-
id,
644-
desc,
645-
monitor_ch,
646-
Box::new(move || __rust_begin_short_backtrace(f)),
647-
test_run_opts,
648-
),
649639
}
650640
}
651641

@@ -663,7 +653,7 @@ fn run_test_in_process(
663653
desc: TestDesc,
664654
nocapture: bool,
665655
report_time: bool,
666-
testfn: Box<dyn FnOnce() -> Result<(), String> + Send>,
656+
runnable_test: RunnableTest,
667657
monitor_ch: Sender<CompletedTest>,
668658
time_opts: Option<time::TestTimeOptions>,
669659
) {
@@ -675,7 +665,7 @@ fn run_test_in_process(
675665
}
676666

677667
let start = report_time.then(Instant::now);
678-
let result = fold_err(catch_unwind(AssertUnwindSafe(testfn)));
668+
let result = fold_err(catch_unwind(AssertUnwindSafe(|| runnable_test.run())));
679669
let exec_time = start.map(|start| {
680670
let duration = start.elapsed();
681671
TestExecTime(duration)
@@ -760,10 +750,7 @@ fn spawn_test_subprocess(
760750
monitor_ch.send(message).unwrap();
761751
}
762752

763-
fn run_test_in_spawned_subprocess(
764-
desc: TestDesc,
765-
testfn: Box<dyn FnOnce() -> Result<(), String> + Send>,
766-
) -> ! {
753+
fn run_test_in_spawned_subprocess(desc: TestDesc, runnable_test: RunnableTest) -> ! {
767754
let builtin_panic_hook = panic::take_hook();
768755
let record_result = Arc::new(move |panic_info: Option<&'_ PanicInfo<'_>>| {
769756
let test_result = match panic_info {
@@ -789,7 +776,7 @@ fn run_test_in_spawned_subprocess(
789776
});
790777
let record_result2 = record_result.clone();
791778
panic::set_hook(Box::new(move |info| record_result2(Some(info))));
792-
if let Err(message) = testfn() {
779+
if let Err(message) = runnable_test.run() {
793780
panic!("{}", message);
794781
}
795782
record_result(None);

library/test/src/types.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22
33
use std::borrow::Cow;
44
use std::fmt;
5+
use std::sync::mpsc::Sender;
56

7+
use super::__rust_begin_short_backtrace;
68
use super::bench::Bencher;
9+
use super::event::CompletedTest;
710
use super::options;
811

912
pub use NamePadding::*;
@@ -95,6 +98,15 @@ impl TestFn {
9598
DynBenchFn(..) => PadOnRight,
9699
}
97100
}
101+
102+
pub(crate) fn into_runnable(self) -> Runnable {
103+
match self {
104+
StaticTestFn(f) => Runnable::Test(RunnableTest::Static(f)),
105+
StaticBenchFn(f) => Runnable::Bench(RunnableBench::Static(f)),
106+
DynTestFn(f) => Runnable::Test(RunnableTest::Dynamic(f)),
107+
DynBenchFn(f) => Runnable::Bench(RunnableBench::Dynamic(f)),
108+
}
109+
}
98110
}
99111

100112
impl fmt::Debug for TestFn {
@@ -108,6 +120,56 @@ impl fmt::Debug for TestFn {
108120
}
109121
}
110122

123+
pub(crate) enum Runnable {
124+
Test(RunnableTest),
125+
Bench(RunnableBench),
126+
}
127+
128+
pub(crate) enum RunnableTest {
129+
Static(fn() -> Result<(), String>),
130+
Dynamic(Box<dyn FnOnce() -> Result<(), String> + Send>),
131+
}
132+
133+
impl RunnableTest {
134+
pub(crate) fn run(self) -> Result<(), String> {
135+
match self {
136+
RunnableTest::Static(f) => __rust_begin_short_backtrace(f),
137+
RunnableTest::Dynamic(f) => __rust_begin_short_backtrace(f),
138+
}
139+
}
140+
141+
pub(crate) fn is_dynamic(&self) -> bool {
142+
match self {
143+
RunnableTest::Static(_) => false,
144+
RunnableTest::Dynamic(_) => true,
145+
}
146+
}
147+
}
148+
149+
pub(crate) enum RunnableBench {
150+
Static(fn(&mut Bencher) -> Result<(), String>),
151+
Dynamic(Box<dyn Fn(&mut Bencher) -> Result<(), String> + Send>),
152+
}
153+
154+
impl RunnableBench {
155+
pub(crate) fn run(
156+
self,
157+
id: TestId,
158+
desc: &TestDesc,
159+
monitor_ch: &Sender<CompletedTest>,
160+
nocapture: bool,
161+
) {
162+
match self {
163+
RunnableBench::Static(f) => {
164+
crate::bench::benchmark(id, desc.clone(), monitor_ch.clone(), nocapture, f)
165+
}
166+
RunnableBench::Dynamic(f) => {
167+
crate::bench::benchmark(id, desc.clone(), monitor_ch.clone(), nocapture, f)
168+
}
169+
}
170+
}
171+
}
172+
111173
// A unique integer associated with each test.
112174
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
113175
pub struct TestId(pub usize);

0 commit comments

Comments
 (0)