From 1850c3a62898519ddd5937c0b29fbc6b2b4920c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edvard=20Th=C3=B6rnros?= Date: Tue, 9 Feb 2021 00:01:12 +0100 Subject: test timeout for those pesky infinet loops --- src/lib.rs | 46 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 37 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index eaa2399..ee5dae8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -729,27 +729,55 @@ mod tests { }; } + use std::time::Duration; + use std::sync::mpsc; + use std::thread; + + // Shamelessly stolen from https://github.com/rust-lang/rfcs/issues/2798 + pub fn panic_after(d: Duration, f: F) -> T + where + T: Send + 'static, + F: FnOnce() -> T, + F: Send + 'static, + { + let (done_tx, done_rx) = mpsc::channel(); + let handle = thread::spawn(move || { + let val = f(); + done_tx.send(()).expect("Unable to send completion signal"); + val + }); + + match done_rx.recv_timeout(d) { + Ok(_) => handle.join().expect("Thread panicked"), + Err(_) => panic!("Thread took too long"), + } + } + #[macro_export] macro_rules! test_string { ($fn:ident, $prog:literal) => { #[test] fn $fn() { - match $crate::run_string($prog, true, Vec::new()) { - Ok(()) => {}, - Err(errs) => { - for e in errs.iter() { - println!("{}", e); + crate::tests::panic_after(std::time::Duration::from_millis(500), || { + match $crate::run_string($prog, true, Vec::new()) { + Ok(()) => {}, + Err(errs) => { + for e in errs.iter() { + println!("{}", e); + } + println!(" {} - FAILED\n", stringify!($fn)); + panic!(); } - println!(" {} - FAILED\n", stringify!($fn)); - panic!(); } - } + }); } }; ($fn:ident, $prog:literal, $errs:tt) => { #[test] fn $fn() { - $crate::assert_errs!($crate::run_string($prog, true, Vec::new()), $errs); + crate::tests::panic_after(std::time::Duration::from_millis(500), || { + $crate::assert_errs!($crate::run_string($prog, true, Vec::new()), $errs); + }) } } } -- cgit v1.2.1