Skip to content

Commit

Permalink
Add parameter for timeout on a per test level
Browse files Browse the repository at this point in the history
Signed-off-by: Heinz N. Gies <heinz@licenser.net>
  • Loading branch information
Licenser committed Jul 1, 2022
1 parent 1ff7071 commit 8540580
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 95 deletions.
31 changes: 3 additions & 28 deletions serial_test/src/code_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,6 @@ lazy_static! {
static ref MUTEX_ID: Arc<AtomicU32> = Arc::new(AtomicU32::new(1));
}

#[cfg(feature = "timeout")]
lazy_static! {
static ref MAX_WAIT: Arc<RwLock<Duration>> = Arc::new(RwLock::new(Duration::from_secs(60)));
}

impl Default for UniqueReentrantMutex {
fn default() -> Self {
Self {
Expand All @@ -64,27 +59,7 @@ impl Default for UniqueReentrantMutex {
}
}

/// Sets the maximum amount of time the serial locks will wait to unlock.
/// By default, this is set to 60 seconds, which is almost always much longer than is needed.
/// This is deliberately set high to try and avoid situations where we accidentally hit the limits
/// but is set at all so we can timeout rather than hanging forever.
///
/// However, sometimes if you've got a *lot* of serial tests it might theoretically not be enough,
/// hence this method.
///
/// This function is only available when the `timeout` feature is enabled.
#[cfg(feature = "timeout")]
pub fn set_max_wait(max_wait: Duration) {
*MAX_WAIT.write() = max_wait;
}

#[cfg(feature = "timeout")]
pub(crate) fn wait_duration() -> Duration {
*MAX_WAIT.read()
}

pub(crate) fn check_new_key(name: &str) {
#[cfg(feature = "timeout")]
pub(crate) fn check_new_key(name: &str, max_wait: Option<Duration>) {
let start = Instant::now();
loop {
#[cfg(all(feature = "logging", feature = "timeout"))]
Expand Down Expand Up @@ -115,9 +90,9 @@ pub(crate) fn check_new_key(name: &str) {
// Odds are another test was also locking on the write and has now written the key

#[cfg(feature = "timeout")]
{
if let Some(max_wait) = max_wait {
let duration = start.elapsed();
if duration > wait_duration() {
if duration > max_wait {
panic!("Timeout waiting for '{}' {:?}", name, duration);
}
}
Expand Down
2 changes: 0 additions & 2 deletions serial_test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ mod parallel_file_lock;
#[cfg(feature = "file_locks")]
mod serial_file_lock;

#[cfg(feature = "timeout")]
pub use code_lock::set_max_wait;
pub use parallel_code_lock::{
local_async_parallel_core, local_async_parallel_core_with_return, local_parallel_core,
local_parallel_core_with_return,
Expand Down
22 changes: 14 additions & 8 deletions serial_test/src/parallel_code_lock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

use crate::code_lock::{check_new_key, LOCKS};
use futures::FutureExt;
use std::{ops::Deref, panic};
use std::{ops::Deref, panic, time::Duration};

#[doc(hidden)]
pub fn local_parallel_core_with_return<E>(
name: &str,
max_wait: Option<Duration>,
function: fn() -> Result<(), E>,
) -> Result<(), E> {
check_new_key(name);
check_new_key(name, max_wait);

let unlock = LOCKS.read_recursive();
unlock.deref()[name].start_parallel();
Expand All @@ -24,8 +25,8 @@ pub fn local_parallel_core_with_return<E>(
}

#[doc(hidden)]
pub fn local_parallel_core(name: &str, function: fn()) {
check_new_key(name);
pub fn local_parallel_core(name: &str, max_wait: Option<Duration>, function: fn()) {
check_new_key(name, max_wait);

let unlock = LOCKS.read_recursive();
unlock.deref()[name].start_parallel();
Expand All @@ -41,9 +42,10 @@ pub fn local_parallel_core(name: &str, function: fn()) {
#[doc(hidden)]
pub async fn local_async_parallel_core_with_return<E>(
name: &str,
max_wait: Option<Duration>,
fut: impl std::future::Future<Output = Result<(), E>> + panic::UnwindSafe,
) -> Result<(), E> {
check_new_key(name);
check_new_key(name, max_wait);

let unlock = LOCKS.read_recursive();
unlock.deref()[name].start_parallel();
Expand All @@ -60,9 +62,10 @@ pub async fn local_async_parallel_core_with_return<E>(
#[doc(hidden)]
pub async fn local_async_parallel_core(
name: &str,
max_wait: Option<Duration>,
fut: impl std::future::Future<Output = ()> + panic::UnwindSafe,
) {
check_new_key(name);
check_new_key(name, max_wait);

let unlock = LOCKS.read_recursive();
unlock.deref()[name].start_parallel();
Expand All @@ -84,7 +87,7 @@ mod tests {
#[test]
fn unlock_on_assert_sync_without_return() {
let _ = panic::catch_unwind(|| {
local_parallel_core("unlock_on_assert_sync_without_return", || {
local_parallel_core("unlock_on_assert_sync_without_return", None, || {
assert!(false);
})
});
Expand All @@ -100,6 +103,7 @@ mod tests {
let _ = panic::catch_unwind(|| {
local_parallel_core_with_return(
"unlock_on_assert_sync_with_return",
None,
|| -> Result<(), Error> {
assert!(false);
Ok(())
Expand All @@ -119,7 +123,8 @@ mod tests {
assert!(false);
}
async fn call_serial_test_fn() {
local_async_parallel_core("unlock_on_assert_async_without_return", demo_assert()).await
local_async_parallel_core("unlock_on_assert_async_without_return", None, demo_assert())
.await
}
// as per https://stackoverflow.com/a/66529014/320546
let _ = panic::catch_unwind(|| {
Expand All @@ -145,6 +150,7 @@ mod tests {
async fn call_serial_test_fn() {
local_async_parallel_core_with_return(
"unlock_on_assert_async_with_return",
None,
demo_assert(),
)
.await;
Expand Down
24 changes: 15 additions & 9 deletions serial_test/src/serial_code_lock.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#![allow(clippy::await_holding_lock)]

use crate::code_lock::{check_new_key, LOCKS};
use std::ops::Deref;
use std::{ops::Deref, time::Duration};

#[doc(hidden)]
pub fn local_serial_core_with_return<E>(
name: &str,
max_wait: Option<Duration>,
function: fn() -> Result<(), E>,
) -> Result<(), E> {
check_new_key(name);
check_new_key(name, max_wait);

let unlock = LOCKS.read_recursive();
// _guard needs to be named to avoid being instant dropped
Expand All @@ -17,8 +18,8 @@ pub fn local_serial_core_with_return<E>(
}

#[doc(hidden)]
pub fn local_serial_core(name: &str, function: fn()) {
check_new_key(name);
pub fn local_serial_core(name: &str, max_wait: Option<Duration>, function: fn()) {
check_new_key(name, max_wait);

let unlock = LOCKS.read_recursive();
// _guard needs to be named to avoid being instant dropped
Expand All @@ -29,9 +30,10 @@ pub fn local_serial_core(name: &str, function: fn()) {
#[doc(hidden)]
pub async fn local_async_serial_core_with_return<E>(
name: &str,
max_wait: Option<Duration>,
fut: impl std::future::Future<Output = Result<(), E>>,
) -> Result<(), E> {
check_new_key(name);
check_new_key(name, max_wait);

let unlock = LOCKS.read_recursive();
// _guard needs to be named to avoid being instant dropped
Expand All @@ -40,8 +42,12 @@ pub async fn local_async_serial_core_with_return<E>(
}

#[doc(hidden)]
pub async fn local_async_serial_core(name: &str, fut: impl std::future::Future<Output = ()>) {
check_new_key(name);
pub async fn local_async_serial_core(
name: &str,
max_wait: Option<Duration>,
fut: impl std::future::Future<Output = ()>,
) {
check_new_key(name, max_wait);

let unlock = LOCKS.read_recursive();
// _guard needs to be named to avoid being instant dropped
Expand Down Expand Up @@ -77,7 +83,7 @@ mod tests {
let c = barrier.clone();
threads.push(thread::spawn(move || {
c.wait();
check_new_key("foo");
check_new_key("foo", None);
{
let unlock = local_locks
.try_read_recursive_for(Duration::from_secs(1))
Expand Down Expand Up @@ -107,7 +113,7 @@ mod tests {
#[test]
fn unlock_on_assert() {
let _ = std::panic::catch_unwind(|| {
local_serial_core("assert", || {
local_serial_core("assert", None, || {
assert!(false);
})
});
Expand Down
2 changes: 1 addition & 1 deletion serial_test/tests/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use serial_test::local_serial_core;

#[test]
fn test_empty_serial_call() {
local_serial_core("beta", || {
local_serial_core("beta", None, || {
println!("Bar");
});
}

0 comments on commit 8540580

Please sign in to comment.