Warn when a #[should_panic] test has an unexpected message

This commit is contained in:
Josh Driver
2016-11-18 21:01:19 +10:30
parent d6689fdc61
commit fb5ccf80fe
3 changed files with 68 additions and 13 deletions

View File

@@ -75,9 +75,9 @@ const TEST_WARN_TIMEOUT_S: u64 = 60;
// to be used by rustc to compile tests in libtest // to be used by rustc to compile tests in libtest
pub mod test { pub mod test {
pub use {Bencher, TestName, TestResult, TestDesc, TestDescAndFn, TestOpts, TrFailed, pub use {Bencher, TestName, TestResult, TestDesc, TestDescAndFn, TestOpts, TrFailed,
TrIgnored, TrOk, Metric, MetricMap, StaticTestFn, StaticTestName, DynTestName, TrFailedMsg, TrIgnored, TrOk, Metric, MetricMap, StaticTestFn, StaticTestName,
DynTestFn, run_test, test_main, test_main_static, filter_tests, parse_opts, DynTestName, DynTestFn, run_test, test_main, test_main_static, filter_tests,
StaticBenchFn, ShouldPanic}; parse_opts, StaticBenchFn, ShouldPanic};
} }
pub mod stats; pub mod stats;
@@ -473,6 +473,7 @@ pub struct BenchSamples {
pub enum TestResult { pub enum TestResult {
TrOk, TrOk,
TrFailed, TrFailed,
TrFailedMsg(String),
TrIgnored, TrIgnored,
TrMetrics(MetricMap), TrMetrics(MetricMap),
TrBench(BenchSamples), TrBench(BenchSamples),
@@ -611,7 +612,7 @@ impl<T: Write> ConsoleTestState<T> {
pub fn write_result(&mut self, result: &TestResult) -> io::Result<()> { pub fn write_result(&mut self, result: &TestResult) -> io::Result<()> {
match *result { match *result {
TrOk => self.write_ok(), TrOk => self.write_ok(),
TrFailed => self.write_failed(), TrFailed | TrFailedMsg(_) => self.write_failed(),
TrIgnored => self.write_ignored(), TrIgnored => self.write_ignored(),
TrMetrics(ref mm) => { TrMetrics(ref mm) => {
self.write_metric()?; self.write_metric()?;
@@ -638,6 +639,7 @@ impl<T: Write> ConsoleTestState<T> {
match *result { match *result {
TrOk => "ok".to_owned(), TrOk => "ok".to_owned(),
TrFailed => "failed".to_owned(), TrFailed => "failed".to_owned(),
TrFailedMsg(ref msg) => format!("failed: {}", msg),
TrIgnored => "ignored".to_owned(), TrIgnored => "ignored".to_owned(),
TrMetrics(ref mm) => mm.fmt_metrics(), TrMetrics(ref mm) => mm.fmt_metrics(),
TrBench(ref bs) => fmt_bench_samples(bs), TrBench(ref bs) => fmt_bench_samples(bs),
@@ -773,6 +775,14 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
st.failed += 1; st.failed += 1;
st.failures.push((test, stdout)); st.failures.push((test, stdout));
} }
TrFailedMsg(msg) => {
st.failed += 1;
let mut stdout = stdout;
stdout.extend_from_slice(
format!("note: {}", msg).as_bytes()
);
st.failures.push((test, stdout));
}
} }
Ok(()) Ok(())
} }
@@ -1270,12 +1280,16 @@ fn calc_result(desc: &TestDesc, task_result: Result<(), Box<Any + Send>>) -> Tes
match (&desc.should_panic, task_result) { match (&desc.should_panic, task_result) {
(&ShouldPanic::No, Ok(())) | (&ShouldPanic::No, Ok(())) |
(&ShouldPanic::Yes, Err(_)) => TrOk, (&ShouldPanic::Yes, Err(_)) => TrOk,
(&ShouldPanic::YesWithMessage(msg), Err(ref err)) (&ShouldPanic::YesWithMessage(msg), Err(ref err)) =>
if err.downcast_ref::<String>() if err.downcast_ref::<String>()
.map(|e| &**e) .map(|e| &**e)
.or_else(|| err.downcast_ref::<&'static str>().map(|e| *e)) .or_else(|| err.downcast_ref::<&'static str>().map(|e| *e))
.map(|e| e.contains(msg)) .map(|e| e.contains(msg))
.unwrap_or(false) => TrOk, .unwrap_or(false) {
TrOk
} else {
TrFailedMsg(format!("Panic did not include expected string '{}'", msg))
},
_ => TrFailed, _ => TrFailed,
} }
} }
@@ -1482,8 +1496,9 @@ pub mod bench {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use test::{TrFailed, TrIgnored, TrOk, filter_tests, parse_opts, TestDesc, TestDescAndFn, use test::{TrFailed, TrFailedMsg, TrIgnored, TrOk, filter_tests, parse_opts, TestDesc,
TestOpts, run_test, MetricMap, StaticTestName, DynTestName, DynTestFn, ShouldPanic}; TestDescAndFn, TestOpts, run_test, MetricMap, StaticTestName, DynTestName,
DynTestFn, ShouldPanic};
use std::sync::mpsc::channel; use std::sync::mpsc::channel;
#[test] #[test]
@@ -1565,18 +1580,20 @@ mod tests {
fn f() { fn f() {
panic!("an error message"); panic!("an error message");
} }
let expected = "foobar";
let failed_msg = "Panic did not include expected string";
let desc = TestDescAndFn { let desc = TestDescAndFn {
desc: TestDesc { desc: TestDesc {
name: StaticTestName("whatever"), name: StaticTestName("whatever"),
ignore: false, ignore: false,
should_panic: ShouldPanic::YesWithMessage("foobar"), should_panic: ShouldPanic::YesWithMessage(expected),
}, },
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);
let (_, res, _) = rx.recv().unwrap(); let (_, res, _) = rx.recv().unwrap();
assert!(res == TrFailed); assert!(res == TrFailedMsg(format!("{} '{}'", failed_msg, expected)));
} }
#[test] #[test]

View File

@@ -0,0 +1,19 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: --test
// error-pattern:panicked at 'bar'
// check-stdout
#[test]
#[should_panic(expected = "foo")]
pub fn test_bar() {
panic!("bar")
}

View File

@@ -0,0 +1,19 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-flags: --test
// error-pattern:panicked at 'explicit panic'
// check-stdout
#[test]
#[should_panic(expected = "foo")]
pub fn test_explicit() {
panic!()
}