std: Minor cleanup to libtest

* Don't spawn two threads for all tests, just one now that `catch_unwind` is
  stable.
* Remove usage of the unstable `box` keyword
* Remove usage of the unstable `FnBox` trait
This commit is contained in:
Alex Crichton 2016-10-05 09:50:15 -07:00
parent 7a26aeca77
commit 0714024c99
3 changed files with 67 additions and 67 deletions

View File

@ -443,7 +443,7 @@ impl Collector {
// compiler failures are test failures // compiler failures are test failures
should_panic: testing::ShouldPanic::No, should_panic: testing::ShouldPanic::No,
}, },
testfn: testing::DynTestFn(box move|| { testfn: testing::DynTestFn(box move |()| {
runtest(&test, runtest(&test,
&cratename, &cratename,
cfgs, cfgs,

View File

@ -34,8 +34,6 @@
#![cfg_attr(not(stage0), deny(warnings))] #![cfg_attr(not(stage0), deny(warnings))]
#![feature(asm)] #![feature(asm)]
#![feature(box_syntax)]
#![feature(fnbox)]
#![feature(libc)] #![feature(libc)]
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(set_stdio)] #![feature(set_stdio)]
@ -56,8 +54,7 @@ use self::TestEvent::*;
use self::NamePadding::*; use self::NamePadding::*;
use self::OutputLocation::*; use self::OutputLocation::*;
use std::boxed::FnBox; use std::panic::{catch_unwind, AssertUnwindSafe};
use std::any::Any; use std::any::Any;
use std::cmp; use std::cmp;
use std::collections::BTreeMap; use std::collections::BTreeMap;
@ -135,6 +132,16 @@ pub trait TDynBenchFn: Send {
fn run(&self, harness: &mut Bencher); fn run(&self, harness: &mut Bencher);
} }
pub trait FnBox<T>: Send + 'static {
fn call_box(self: Box<Self>, t: T);
}
impl<T, F: FnOnce(T) + Send + 'static> FnBox<T> for F {
fn call_box(self: Box<F>, t: T) {
(*self)(t)
}
}
// A function that runs a test. If the function returns successfully, // A function that runs a test. If the function returns successfully,
// the test succeeds; if the function panics then the test fails. We // the test succeeds; if the function panics then the test fails. We
// may need to come up with a more clever definition of test in order // may need to come up with a more clever definition of test in order
@ -143,8 +150,8 @@ pub enum TestFn {
StaticTestFn(fn()), StaticTestFn(fn()),
StaticBenchFn(fn(&mut Bencher)), StaticBenchFn(fn(&mut Bencher)),
StaticMetricFn(fn(&mut MetricMap)), StaticMetricFn(fn(&mut MetricMap)),
DynTestFn(Box<FnBox() + Send>), DynTestFn(Box<FnBox<()>>),
DynMetricFn(Box<FnBox(&mut MetricMap) + Send>), DynMetricFn(Box<for<'a> FnBox<&'a mut MetricMap>>),
DynBenchFn(Box<TDynBenchFn + 'static>), DynBenchFn(Box<TDynBenchFn + 'static>),
} }
@ -1137,23 +1144,25 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA
pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> { pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> {
// convert benchmarks to tests, if we're not benchmarking them // convert benchmarks to tests, if we're not benchmarking them
tests.into_iter() tests.into_iter().map(|x| {
.map(|x| { let testfn = match x.testfn {
let testfn = match x.testfn { DynBenchFn(bench) => {
DynBenchFn(bench) => { DynTestFn(Box::new(move |()| {
DynTestFn(Box::new(move || bench::run_once(|b| bench.run(b)))) bench::run_once(|b| bench.run(b))
} }))
StaticBenchFn(benchfn) => { }
DynTestFn(Box::new(move || bench::run_once(|b| benchfn(b)))) StaticBenchFn(benchfn) => {
} DynTestFn(Box::new(move |()| {
f => f, bench::run_once(|b| benchfn(b))
}; }))
TestDescAndFn { }
desc: x.desc, f => f,
testfn: testfn, };
} TestDescAndFn {
}) desc: x.desc,
.collect() testfn: testfn,
}
}).collect()
} }
pub fn run_test(opts: &TestOpts, pub fn run_test(opts: &TestOpts,
@ -1171,7 +1180,7 @@ pub fn run_test(opts: &TestOpts,
fn run_test_inner(desc: TestDesc, fn run_test_inner(desc: TestDesc,
monitor_ch: Sender<MonitorMsg>, monitor_ch: Sender<MonitorMsg>,
nocapture: bool, nocapture: bool,
testfn: Box<FnBox() + Send>) { testfn: Box<FnBox<()>>) {
struct Sink(Arc<Mutex<Vec<u8>>>); struct Sink(Arc<Mutex<Vec<u8>>>);
impl Write for Sink { impl Write for Sink {
fn write(&mut self, data: &[u8]) -> io::Result<usize> { fn write(&mut self, data: &[u8]) -> io::Result<usize> {
@ -1182,48 +1191,23 @@ pub fn run_test(opts: &TestOpts,
} }
} }
// If the platform is single-threaded we're just going to run
// the test synchronously, regardless of the concurrency
// level.
let supports_threads = !cfg!(target_os = "emscripten");
// Buffer for capturing standard I/O // Buffer for capturing standard I/O
let data = Arc::new(Mutex::new(Vec::new())); let data = Arc::new(Mutex::new(Vec::new()));
let data2 = data.clone(); let data2 = data.clone();
if supports_threads { let name = desc.name.clone();
thread::spawn(move || { let runtest = move || {
let cfg = thread::Builder::new().name(match desc.name {
DynTestName(ref name) => name.clone(),
StaticTestName(name) => name.to_owned(),
});
let result_guard = cfg.spawn(move || {
if !nocapture {
io::set_print(Some(box Sink(data2.clone())));
io::set_panic(Some(box Sink(data2)));
}
testfn()
})
.unwrap();
let test_result = calc_result(&desc, result_guard.join());
let stdout = data.lock().unwrap().to_vec();
monitor_ch.send((desc.clone(), test_result, stdout)).unwrap();
});
} else {
let oldio = if !nocapture { let oldio = if !nocapture {
Some(( Some((
io::set_print(Some(box Sink(data2.clone()))), io::set_print(Some(Box::new(Sink(data2.clone())))),
io::set_panic(Some(box Sink(data2))) io::set_panic(Some(Box::new(Sink(data2))))
)) ))
} else { } else {
None None
}; };
use std::panic::{catch_unwind, AssertUnwindSafe};
let result = catch_unwind(AssertUnwindSafe(|| { let result = catch_unwind(AssertUnwindSafe(|| {
testfn() testfn.call_box(())
})); }));
if let Some((printio, panicio)) = oldio { if let Some((printio, panicio)) = oldio {
@ -1234,6 +1218,21 @@ pub fn run_test(opts: &TestOpts,
let test_result = calc_result(&desc, result); let test_result = calc_result(&desc, result);
let stdout = data.lock().unwrap().to_vec(); let stdout = data.lock().unwrap().to_vec();
monitor_ch.send((desc.clone(), test_result, stdout)).unwrap(); monitor_ch.send((desc.clone(), test_result, stdout)).unwrap();
};
// If the platform is single-threaded we're just going to run
// the test synchronously, regardless of the concurrency
// level.
let supports_threads = !cfg!(target_os = "emscripten");
if supports_threads {
let cfg = thread::Builder::new().name(match name {
DynTestName(ref name) => name.clone(),
StaticTestName(name) => name.to_owned(),
});
cfg.spawn(runtest).unwrap();
} else {
runtest();
} }
} }
@ -1250,7 +1249,7 @@ pub fn run_test(opts: &TestOpts,
} }
DynMetricFn(f) => { DynMetricFn(f) => {
let mut mm = MetricMap::new(); let mut mm = MetricMap::new();
f.call_box((&mut mm,)); f.call_box(&mut mm);
monitor_ch.send((desc, TrMetrics(mm), Vec::new())).unwrap(); monitor_ch.send((desc, TrMetrics(mm), Vec::new())).unwrap();
return; return;
} }
@ -1261,7 +1260,8 @@ pub fn run_test(opts: &TestOpts,
return; return;
} }
DynTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, f), DynTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, f),
StaticTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture, Box::new(f)), StaticTestFn(f) => run_test_inner(desc, monitor_ch, opts.nocapture,
Box::new(move |()| f())),
} }
} }
@ -1496,7 +1496,7 @@ mod tests {
ignore: true, ignore: true,
should_panic: ShouldPanic::No, should_panic: ShouldPanic::No,
}, },
testfn: DynTestFn(Box::new(move || f())), testfn: DynTestFn(Box::new(move |()| f())),
}; };
let (tx, rx) = channel(); let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx); run_test(&TestOpts::new(), false, desc, tx);
@ -1513,7 +1513,7 @@ mod tests {
ignore: true, ignore: true,
should_panic: ShouldPanic::No, should_panic: ShouldPanic::No,
}, },
testfn: DynTestFn(Box::new(move || f())), testfn: DynTestFn(Box::new(move |()| f())),
}; };
let (tx, rx) = channel(); let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx); run_test(&TestOpts::new(), false, desc, tx);
@ -1532,7 +1532,7 @@ mod tests {
ignore: false, ignore: false,
should_panic: ShouldPanic::Yes, should_panic: ShouldPanic::Yes,
}, },
testfn: DynTestFn(Box::new(move || f())), testfn: DynTestFn(Box::new(move |()| f())),
}; };
let (tx, rx) = channel(); let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx); run_test(&TestOpts::new(), false, desc, tx);
@ -1551,7 +1551,7 @@ mod tests {
ignore: false, ignore: false,
should_panic: ShouldPanic::YesWithMessage("error message"), should_panic: ShouldPanic::YesWithMessage("error message"),
}, },
testfn: DynTestFn(Box::new(move || f())), testfn: DynTestFn(Box::new(move |()| f())),
}; };
let (tx, rx) = channel(); let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx); run_test(&TestOpts::new(), false, desc, tx);
@ -1570,7 +1570,7 @@ mod tests {
ignore: false, ignore: false,
should_panic: ShouldPanic::YesWithMessage("foobar"), should_panic: ShouldPanic::YesWithMessage("foobar"),
}, },
testfn: DynTestFn(Box::new(move || f())), testfn: DynTestFn(Box::new(move |()| f())),
}; };
let (tx, rx) = channel(); let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx); run_test(&TestOpts::new(), false, desc, tx);
@ -1587,7 +1587,7 @@ mod tests {
ignore: false, ignore: false,
should_panic: ShouldPanic::Yes, should_panic: ShouldPanic::Yes,
}, },
testfn: DynTestFn(Box::new(move || f())), testfn: DynTestFn(Box::new(move |()| f())),
}; };
let (tx, rx) = channel(); let (tx, rx) = channel();
run_test(&TestOpts::new(), false, desc, tx); run_test(&TestOpts::new(), false, desc, tx);
@ -1620,7 +1620,7 @@ mod tests {
ignore: true, ignore: true,
should_panic: ShouldPanic::No, should_panic: ShouldPanic::No,
}, },
testfn: DynTestFn(Box::new(move || {})), testfn: DynTestFn(Box::new(move |()| {})),
}, },
TestDescAndFn { TestDescAndFn {
desc: TestDesc { desc: TestDesc {
@ -1628,7 +1628,7 @@ mod tests {
ignore: false, ignore: false,
should_panic: ShouldPanic::No, should_panic: ShouldPanic::No,
}, },
testfn: DynTestFn(Box::new(move || {})), testfn: DynTestFn(Box::new(move |()| {})),
}]; }];
let filtered = filter_tests(&opts, tests); let filtered = filter_tests(&opts, tests);
@ -1661,7 +1661,7 @@ mod tests {
ignore: false, ignore: false,
should_panic: ShouldPanic::No, should_panic: ShouldPanic::No,
}, },
testfn: DynTestFn(Box::new(testfn)), testfn: DynTestFn(Box::new(move |()| testfn())),
}; };
tests.push(test); tests.push(test);
} }

View File

@ -464,7 +464,7 @@ pub fn make_test_name(config: &Config, testpaths: &TestPaths) -> test::TestName
pub fn make_test_closure(config: &Config, testpaths: &TestPaths) -> test::TestFn { pub fn make_test_closure(config: &Config, testpaths: &TestPaths) -> test::TestFn {
let config = config.clone(); let config = config.clone();
let testpaths = testpaths.clone(); let testpaths = testpaths.clone();
test::DynTestFn(Box::new(move || { test::DynTestFn(Box::new(move |()| {
runtest::run(config, &testpaths) runtest::run(config, &testpaths)
})) }))
} }