timebomb/
lib.rs

1//   Copyright 2015 Colin Sherratt
2//
3//   Licensed under the Apache License, Version 2.0 (the "License");
4//   you may not use this file except in compliance with the License.
5//   You may obtain a copy of the License at
6//
7//       http://www.apache.org/licenses/LICENSE-2.0
8//
9//   Unless required by applicable law or agreed to in writing, software
10//   distributed under the License is distributed on an "AS IS" BASIS,
11//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//   See the License for the specific language governing permissions and
13//   limitations under the License.
14
15extern crate pulse;
16
17use std::thread;
18use pulse::{Signal, TimeoutError};
19
20/// Run f for at most max_ms, this function will panic if
21/// f is still running.
22pub fn timeout_ms<F>(f: F, max_ms: u32) where F: FnOnce() + Send + 'static {
23    let (signal_start, pulse_start) = Signal::new();
24    let (signal_end, pulse_end) = Signal::new();
25
26    let guard = thread::spawn(|| {
27        pulse_start.pulse();
28        f();
29        pulse_end.pulse();
30    });
31
32    // Wait for the thread to start.
33    // This is done so that a loaded computer
34    // does not timeout before the thread has been started
35    signal_start.wait().unwrap();
36
37    // Wait for the timeout
38    match signal_end.wait_timeout_ms(max_ms) {
39        Err(TimeoutError::Timeout) => {
40            panic!("Timed out");
41        }
42        _ => ()
43    }
44
45    guard.join().unwrap();
46}
47
48#[test]
49fn timeout_ms_no_timeout_ms() {
50    timeout_ms(|| {}, 100);
51}
52
53#[test]
54#[should_panic]
55fn timeout_ms_spin() {
56    timeout_ms(|| loop {}, 100);
57}
58
59#[test]
60#[should_panic]
61fn child_panics() {
62    timeout_ms(|| {
63        panic!("oh no!")
64    }, 100);
65}