The ntest crate with its #[timeout(<ms>)]
macro as mentioned in the comments by SirDarius may be a simpler solution than the following.
As an alternative, there's a crate that allows creation of processes that run closures, which has some test related features. Processes, unlike threads, can be killed if they run too long.
The crate procspawn has this closure feature, and some other nice features useful for tests where timeouts are desired. Another one of these features is serialization of the return value from the code invoked in the child process. The test code can get the result back and check it in a very straightforward way.
The code to be tested:
use std::thread;
use std::time::Duration;
fn runs_long() -> i32
{
thread::sleep(Duration::from_millis(5000));
42
}
Within the same file, we can add some tests with timeouts:
#[cfg(test)]
mod tests {
use std::time::Duration;
use procspawn;
use crate::*;
procspawn::enable_test_support!();
#[test]
fn runs_long_passes()
{
let handle = procspawn::spawn((), |_| runs_long());
match handle.join_timeout(Duration::from_millis(6000)) {
Ok(result) => assert_eq!(result, 42),
Err(e) => panic!("{}", e),
}
}
#[test]
fn runs_long_fails()
{
let handle = procspawn::spawn((), |_| runs_long());
match handle.join_timeout(Duration::from_millis(1000)) {
Ok(result) => assert_eq!(result, 42),
Err(e) => panic!("{}", e),
}
}
}
And running the tests with cargo test
on the command line, we get:
running 3 tests
test tests::procspawn_test_helper ... ok
test tests::runs_long_fails ... FAILED
test tests::runs_long_passes ... ok
failures:
---- tests::runs_long_fails stdout ----
thread 'tests::runs_long_fails' panicked at 'process spawn error: timed out', src/main.rs:50:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
tests::runs_long_fails
test result: FAILED. 2 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 6.01s
error: test failed, to rerun pass '--bin procspawn'
To enable the test support feature, include the following in your Cargo.toml file:
[dependencies]
procspawn = { version = "0.10", features = ["test-support"] }