Skip to content

Commit cb86f38

Browse files
author
Gilad Naaman
committed
libtest: Failing benchmarks no longer crash the harness.
1 parent 360b263 commit cb86f38

File tree

1 file changed

+91
-37
lines changed

1 file changed

+91
-37
lines changed

src/libtest/lib.rs

+91-37
Original file line numberDiff line numberDiff line change
@@ -887,10 +887,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
887887
.map(|t| t.desc.name.as_slice().len())
888888
.unwrap_or(0);
889889

890-
let is_multithreaded = match opts.test_threads {
891-
Some(n) => n > 1,
892-
None => get_concurrency() > 1,
893-
};
890+
let is_multithreaded = opts.test_threads.unwrap_or_else(get_concurrency) > 1;
894891

895892
let mut out: Box<OutputFormatter> = match opts.format {
896893
OutputFormat::Pretty => Box::new(PrettyFormatter::new(
@@ -1014,6 +1011,15 @@ pub enum TestEvent {
10141011

10151012
pub type MonitorMsg = (TestDesc, TestResult, Vec<u8>);
10161013

1014+
struct Sink(Arc<Mutex<Vec<u8>>>);
1015+
impl Write for Sink {
1016+
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
1017+
Write::write(&mut *self.0.lock().unwrap(), data)
1018+
}
1019+
fn flush(&mut self) -> io::Result<()> {
1020+
Ok(())
1021+
}
1022+
}
10171023

10181024
pub fn run_tests<F>(opts: &TestOpts, tests: Vec<TestDescAndFn>, mut callback: F) -> io::Result<()>
10191025
where
@@ -1051,10 +1057,7 @@ where
10511057
_ => false,
10521058
});
10531059

1054-
let concurrency = match opts.test_threads {
1055-
Some(n) => n,
1056-
None => get_concurrency(),
1057-
};
1060+
let concurrency = opts.test_threads.unwrap_or_else(get_concurrency);
10581061

10591062
let mut remaining = filtered_tests;
10601063
remaining.reverse();
@@ -1384,16 +1387,6 @@ pub fn run_test(
13841387
monitor_ch: Sender<MonitorMsg>,
13851388
nocapture: bool,
13861389
testfn: Box<FnBox() + Send>) {
1387-
struct Sink(Arc<Mutex<Vec<u8>>>);
1388-
impl Write for Sink {
1389-
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
1390-
Write::write(&mut *self.0.lock().unwrap(), data)
1391-
}
1392-
fn flush(&mut self) -> io::Result<()> {
1393-
Ok(())
1394-
}
1395-
}
1396-
13971390
// Buffer for capturing standard I/O
13981391
let data = Arc::new(Mutex::new(Vec::new()));
13991392
let data2 = data.clone();
@@ -1438,24 +1431,27 @@ pub fn run_test(
14381431

14391432
match testfn {
14401433
DynBenchFn(bencher) => {
1441-
let bs = ::bench::benchmark(|harness| bencher.run(harness));
1442-
monitor_ch.send((desc, TrBench(bs), Vec::new())).unwrap();
1443-
return;
1434+
::bench::benchmark(desc,
1435+
monitor_ch,
1436+
opts.nocapture,
1437+
|harness| bencher.run(harness));
14441438
}
14451439
StaticBenchFn(benchfn) => {
1446-
let bs = ::bench::benchmark(|harness| (benchfn.clone())(harness));
1447-
monitor_ch.send((desc, TrBench(bs), Vec::new())).unwrap();
1448-
return;
1440+
::bench::benchmark(desc,
1441+
monitor_ch,
1442+
opts.nocapture,
1443+
|harness| (benchfn.clone())(harness));
14491444
}
14501445
DynTestFn(f) => {
14511446
let cb = move || {
14521447
__rust_begin_short_backtrace(f)
14531448
};
14541449
run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(cb))
14551450
}
1456-
StaticTestFn(f) =>
1451+
StaticTestFn(f) => {
14571452
run_test_inner(desc, monitor_ch, opts.nocapture,
1458-
Box::new(move || __rust_begin_short_backtrace(f))),
1453+
Box::new(move || __rust_begin_short_backtrace(f)))
1454+
}
14591455
}
14601456
}
14611457

@@ -1655,11 +1651,14 @@ where
16551651
}
16561652

16571653
pub mod bench {
1654+
use std::panic::{catch_unwind, AssertUnwindSafe};
16581655
use std::cmp;
1656+
use std::io;
1657+
use std::sync::{Arc, Mutex};
16591658
use stats;
1660-
use super::{Bencher, BenchSamples, BenchMode};
1659+
use super::{Bencher, BenchSamples, BenchMode, Sink, MonitorMsg, TestDesc, Sender, TestResult};
16611660

1662-
pub fn benchmark<F>(f: F) -> BenchSamples
1661+
pub fn benchmark<F>(desc: TestDesc, monitor_ch: Sender<MonitorMsg>, nocapture: bool, f: F)
16631662
where
16641663
F: FnMut(&mut Bencher),
16651664
{
@@ -1669,26 +1668,53 @@ pub mod bench {
16691668
bytes: 0,
16701669
};
16711670

1672-
return match bs.bench(f) {
1673-
Some(ns_iter_summ) => {
1671+
let data = Arc::new(Mutex::new(Vec::new()));
1672+
let data2 = data.clone();
1673+
1674+
let oldio = if !nocapture {
1675+
Some((
1676+
io::set_print(Some(Box::new(Sink(data2.clone())))),
1677+
io::set_panic(Some(Box::new(Sink(data2)))),
1678+
))
1679+
} else {
1680+
None
1681+
};
1682+
1683+
let result = catch_unwind(AssertUnwindSafe(|| bs.bench(f)));
1684+
1685+
if let Some((printio, panicio)) = oldio {
1686+
io::set_print(printio);
1687+
io::set_panic(panicio);
1688+
};
1689+
1690+
let test_result = match result { //bs.bench(f) {
1691+
Ok(Some(ns_iter_summ)) => {
16741692
let ns_iter = cmp::max(ns_iter_summ.median as u64, 1);
16751693
let mb_s = bs.bytes * 1000 / ns_iter;
16761694

1677-
BenchSamples {
1695+
let bs = BenchSamples {
16781696
ns_iter_summ,
16791697
mb_s: mb_s as usize,
1680-
}
1698+
};
1699+
TestResult::TrBench(bs)
16811700
}
1682-
None => {
1701+
Ok(None) => {
16831702
// iter not called, so no data.
16841703
// FIXME: error in this case?
16851704
let samples: &mut [f64] = &mut [0.0_f64; 1];
1686-
BenchSamples {
1705+
let bs = BenchSamples {
16871706
ns_iter_summ: stats::Summary::new(samples),
16881707
mb_s: 0,
1689-
}
1708+
};
1709+
TestResult::TrBench(bs)
1710+
}
1711+
Err(_) => {
1712+
TestResult::TrFailed
16901713
}
16911714
};
1715+
1716+
let stdout = data.lock().unwrap().to_vec();
1717+
monitor_ch.send((desc, test_result, stdout)).unwrap();
16921718
}
16931719

16941720
pub fn run_once<F>(f: F)
@@ -2067,14 +2093,42 @@ mod tests {
20672093
#[test]
20682094
pub fn test_bench_no_iter() {
20692095
fn f(_: &mut Bencher) {}
2070-
bench::benchmark(f);
2096+
2097+
let (tx, rx) = channel();
2098+
2099+
let desc = TestDesc {
2100+
name: StaticTestName("f"),
2101+
ignore: false,
2102+
should_panic: ShouldPanic::No,
2103+
allow_fail: false,
2104+
};
2105+
2106+
::bench::benchmark(desc,
2107+
tx,
2108+
true,
2109+
f);
2110+
rx.recv().unwrap();
20712111
}
20722112

20732113
#[test]
20742114
pub fn test_bench_iter() {
20752115
fn f(b: &mut Bencher) {
20762116
b.iter(|| {})
20772117
}
2078-
bench::benchmark(f);
2118+
2119+
let (tx, rx) = channel();
2120+
2121+
let desc = TestDesc {
2122+
name: StaticTestName("f"),
2123+
ignore: false,
2124+
should_panic: ShouldPanic::No,
2125+
allow_fail: false,
2126+
};
2127+
2128+
::bench::benchmark(desc,
2129+
tx,
2130+
true,
2131+
f);
2132+
rx.recv().unwrap();
20792133
}
20802134
}

0 commit comments

Comments
 (0)