Skip to content

Commit

Permalink
Add watchdog timer for tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kotauskas committed Apr 2, 2024
1 parent 895b3b4 commit ee5c97f
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 63 deletions.
26 changes: 14 additions & 12 deletions tests/local_socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,28 @@ use crate::{local_socket::NameTypeSupport, tests::util::*};

fn test_stream(id: &'static str, path: bool) -> TestResult {
use stream::*;
testinit();
let scl = |s, n| server(id, handle_client, s, n, path);
drive_server_and_multiple_clients(scl, client)?;
Ok(())
test_wrapper(move || {
let scl = |s, n| server(id, handle_client, s, n, path);
drive_server_and_multiple_clients(scl, client)?;
Ok(())
})
}

fn test_no_server(id: &'static str, path: bool) -> TestResult {
testinit();
no_server::run_and_verify_error(id, path)
test_wrapper(move || no_server::run_and_verify_error(id, path))
}

macro_rules! tests {
(@querymethod true $e:expr) => { NameTypeSupport::fs_supported($e) };
(@querymethod false $e:expr) => { NameTypeSupport::ns_supported($e) };
(@body $fn:ident $path:ident) => {{
if tests!(@querymethod $path NameTypeSupport::query()) {
$fn(make_id!(), $path)?;
}
Ok(())
}};
(@body $fn:ident $path:ident) => {
test_wrapper(|| {
if tests!(@querymethod $path NameTypeSupport::query()) {
$fn(make_id!(), $path)?;
}
Ok(())
})
};
($fn:ident $nm:ident $path:ident) => {
#[test]
fn $nm() -> TestResult { tests!(@body $fn $path) }
Expand Down
13 changes: 7 additions & 6 deletions tests/named_pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ macro_rules! matrix {
#[test]
fn $nm() -> TestResult {
use $mod::*;
testinit();
let server = matrix!(@dir_s $ty);
drive_server_and_multiple_clients(
|ns, nc| server(make_id!(), ns, nc),
matrix!(@dir_c $ty),
)
test_wrapper(|| {
let server = matrix!(@dir_s $ty);
drive_server_and_multiple_clients(
|ns, nc| server(make_id!(), ns, nc),
matrix!(@dir_c $ty),
)
})
}
)+};
}
Expand Down
4 changes: 2 additions & 2 deletions tests/os/unix/local_socket_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ fn test_inner(path: bool) -> TestResult {

#[test]
fn local_socket_file_mode() -> TestResult {
test_inner(true)
test_wrapper(|| test_inner(true))
}

#[cfg(any(target_os = "linux", target_os = "android"))]
#[test]
fn local_socket_namespaced_mode() -> TestResult {
test_inner(false)
test_wrapper(|| test_inner(false))
}
8 changes: 6 additions & 2 deletions tests/os/windows/local_socket_security_descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ fn get_self_exe(obuf: &mut [MaybeUninit<u16>]) -> io::Result<&U16CStr> {
})
}

#[test]
fn local_socket_security_descriptor() -> TestResult {
fn test_main() -> TestResult {
let sd = {
let mut pathbuf = [MaybeUninit::uninit(); MAX_PATH as _];
let path: OsString = get_self_exe(&mut pathbuf)
Expand Down Expand Up @@ -137,3 +136,8 @@ fn local_socket_security_descriptor() -> TestResult {

Ok(())
}

#[test]
fn local_socket_security_descriptor() -> TestResult {
test_wrapper(test_main)
}
55 changes: 29 additions & 26 deletions tests/tokio_local_socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ mod stream;

use crate::{
local_socket::{tokio::Stream, Name, NameTypeSupport},
tests::util::{self, testinit, TestResult},
tests::util::{self, tokio::test_wrapper, TestResult},
};
use std::{future::Future, pin::Pin, sync::Arc};

#[allow(clippy::type_complexity)]
async fn test_stream(id: &'static str, split: bool, path: bool) -> TestResult {
use stream::*;
testinit();
type Fut = Pin<Box<dyn Future<Output = TestResult> + Send + 'static>>;
type F<T> = Box<dyn Fn(T) -> Fut + Send + Sync>;
let hcl: F<Stream> = if split {
Expand All @@ -33,20 +32,22 @@ async fn test_stream(id: &'static str, split: bool, path: bool) -> TestResult {
macro_rules! matrix {
(@querymethod true $e:expr) => { NameTypeSupport::fs_supported($e) };
(@querymethod false $e:expr) => { NameTypeSupport::ns_supported($e) };
(@body $split:ident $path:ident) => {{
if matrix!(@querymethod $path NameTypeSupport::query()) {
test_stream(make_id!(), $split, $path).await?;
}
Ok(())
}};
(@body $split:ident $path:ident) => {
test_wrapper(async {
if matrix!(@querymethod $path NameTypeSupport::query()) {
test_stream(make_id!(), $split, $path).await?;
}
Ok(())
})
};
($nm:ident false $path:ident) => {
#[tokio::test]
async fn $nm() -> TestResult { matrix!(@body false $path) }
#[test]
fn $nm() -> TestResult { matrix!(@body false $path) }
};
($nm:ident true $path:ident) => {
#[tokio::test]
#[test]
#[cfg(not(windows))]
async fn $nm() -> TestResult { matrix!(@body true $path) }
fn $nm() -> TestResult { matrix!(@body true $path) }
};
($($nm:ident $split:ident $path:ident)+) => { $(matrix!($nm $split $path);)+ };
}
Expand All @@ -58,19 +59,21 @@ matrix! {
stream_namespaced_split true false
}

#[tokio::test]
async fn no_server_file() -> TestResult {
testinit();
if NameTypeSupport::query().fs_supported() {
no_server::run_and_verify_error(true).await?;
}
Ok(())
#[test]
fn no_server_file() -> TestResult {
test_wrapper(async {
if NameTypeSupport::query().fs_supported() {
no_server::run_and_verify_error(true).await?;
}
Ok(())
})
}
#[tokio::test]
async fn no_server_namespaced() -> TestResult {
testinit();
if NameTypeSupport::query().ns_supported() {
no_server::run_and_verify_error(false).await?;
}
Ok(())
#[test]
fn no_server_namespaced() -> TestResult {
test_wrapper(async {
if NameTypeSupport::query().ns_supported() {
no_server::run_and_verify_error(false).await?;
}
Ok(())
})
}
21 changes: 12 additions & 9 deletions tests/tokio_named_pipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ mod bytes;
use crate::{
os::windows::named_pipe::PipeListenerOptions,
tests::util::{
listen_and_pick_name, testinit, tokio::drive_server_and_multiple_clients, TestResult,
listen_and_pick_name,
tokio::{drive_server_and_multiple_clients, test_wrapper},
TestResult,
},
};
use color_eyre::eyre::WrapErr;
Expand All @@ -18,15 +20,16 @@ macro_rules! matrix {
(@dir_s duplex) => {server_duplex}; (@dir_s stc) => {server_stc}; (@dir_s cts) => {server_cts};
(@dir_c duplex) => {client_duplex}; (@dir_c stc) => {client_stc}; (@dir_c cts) => {client_cts};
($($mod:ident $ty:ident $nm:ident)+) => {$(
#[tokio::test]
async fn $nm() -> TestResult {
#[test]
fn $nm() -> TestResult {
use $mod::*;
testinit();
let server = matrix!(@dir_s $ty);
drive_server_and_multiple_clients(
move |ns, nc| server(make_id!(), ns, nc),
matrix!(@dir_c $ty),
).await
test_wrapper(async {
let server = matrix!(@dir_s $ty);
drive_server_and_multiple_clients(
move |ns, nc| server(make_id!(), ns, nc),
matrix!(@dir_c $ty),
).await
})
}
)+};
}
Expand Down
11 changes: 6 additions & 5 deletions tests/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
//! it.
#![allow(dead_code, unused_macros)]

mod choke;

mod drive;
#[macro_use]
mod eyre;
mod xorshift;
#[macro_use]
mod namegen;
mod choke;
mod drive;
mod wdt;
mod xorshift;

#[allow(unused_imports)]
pub use {drive::*, eyre::*, namegen::*, xorshift::*};
Expand All @@ -23,8 +23,9 @@ const NUM_CONCURRENT_CLIENTS: u32 = 6;
use color_eyre::eyre::WrapErr;
use std::{fmt::Arguments, io, sync::Arc};

pub fn testinit() {
pub fn test_wrapper(f: impl (FnOnce() -> TestResult) + Send + 'static) -> TestResult {
eyre::install();
self::wdt::run_under_wachdog(f)
}

pub fn message(msg: Option<Arguments<'_>>, server: bool, terminator: Option<char>) -> Box<str> {
Expand Down
12 changes: 11 additions & 1 deletion tests/util/tokio.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{TestResult, NUM_CLIENTS, NUM_CONCURRENT_CLIENTS};
use super::{TestResult, WrapErrExt, NUM_CLIENTS, NUM_CONCURRENT_CLIENTS};
use color_eyre::eyre::{bail, Context};
use std::{future::Future, sync::Arc};
use tokio::{
Expand All @@ -9,6 +9,16 @@ use tokio::{
task, try_join,
};

pub fn test_wrapper(f: impl Future<Output = TestResult> + Send + 'static) -> TestResult {
super::test_wrapper(|| {
let rt = tokio::runtime::Builder::new_current_thread()
.enable_io()
.build()
.opname("Tokio runtime spawn")?;
rt.block_on(f)
})
}

/// Waits for the leader closure to reach a point where it sends a message for the follower closure,
/// then runs the follower. Captures Eyre errors on both sides and panics if any occur, reporting
/// which side produced the error.
Expand Down
21 changes: 21 additions & 0 deletions tests/util/wdt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use super::{TestResult, WrapErrExt};
use color_eyre::eyre::bail;
use std::{sync::mpsc, thread, time::Duration};

const TIMEOUT: Duration = Duration::from_secs(2);

pub fn run_under_wachdog(f: impl (FnOnce() -> TestResult) + Send + 'static) -> TestResult {
let (killswitch, timeout_joiner) = mpsc::channel();
let joiner = thread::Builder::new()
.name("test main (under watchdog)".to_owned())
.spawn(move || {
let ret = f();
let _ = killswitch.send(());
ret
})
.opname("watchdog scrutinee thread spawn")?;
if let Err(mpsc::RecvTimeoutError::Timeout) = timeout_joiner.recv_timeout(TIMEOUT) {
bail!("watchdog timer has run out");
}
joiner.join().unwrap()
}

0 comments on commit ee5c97f

Please sign in to comment.