From 362e10edbffbdf271d90a98f9e87bd997a83aa6b Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Wed, 29 Jun 2022 12:40:20 +0200 Subject: [PATCH 1/3] Intoduce timeout as a feature Signed-off-by: Heinz N. Gies --- serial_test/Cargo.toml | 18 ++++++++++++------ serial_test/src/code_lock.rs | 30 +++++++++++++++++++----------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/serial_test/Cargo.toml b/serial_test/Cargo.toml index 7665da5..525feed 100644 --- a/serial_test/Cargo.toml +++ b/serial_test/Cargo.toml @@ -14,17 +14,19 @@ keywords = ["sequential"] lazy_static = "1.2" parking_lot = "^0.12" serial_test_derive = { version = "~0.8.0", path = "../serial_test_derive" } -fslock = {version = "0.2", optional = true} -document-features = {version = "0.2", optional=true} -log = {version = "0.4", optional = true} -futures = {version = "^0.3", default_features = false, features = ["executor"] } +fslock = { version = "0.2", optional = true } +document-features = { version = "0.2", optional = true } +log = { version = "0.4", optional = true } +futures = { version = "^0.3", default_features = false, features = [ + "executor", +] } [dev-dependencies] itertools = "0.10" tokio = { version = "^1.17", features = ["macros", "rt"] } [features] -default = ["logging"] +default = ["logging", "timeout"] ## Switches on debug logging (and requires the `log` package) logging = ["log"] @@ -32,10 +34,14 @@ logging = ["log"] ## The file_locks feature unlocks the `file_serial`/`file_parallel` macros file_locks = ["fslock"] +## The `timeout` feature lets tests time out after a certain amount of time +## if not enabled tests will wait indefinetly to be started +timeout = [] + docsrs = ["document-features"] # docs.rs-specific configuration [package.metadata.docs.rs] all-features = true # defines the configuration attribute `docsrs` -rustdoc-args = ["--cfg", "docsrs"] \ No newline at end of file +rustdoc-args = ["--cfg", "docsrs"] diff --git a/serial_test/src/code_lock.rs b/serial_test/src/code_lock.rs index 0835335..ec0f24d 100644 --- a/serial_test/src/code_lock.rs +++ b/serial_test/src/code_lock.rs @@ -2,9 +2,8 @@ use crate::rwlock::{Locks, MutexGuardWrapper}; use lazy_static::lazy_static; #[cfg(feature = "logging")] use log::debug; -use parking_lot::{Mutex, RwLock}; +use parking_lot::RwLock; use std::{ - cell::RefCell, collections::HashMap, ops::{Deref, DerefMut}, sync::{atomic::AtomicU32, Arc}, @@ -46,11 +45,14 @@ impl UniqueReentrantMutex { lazy_static! { pub(crate) static ref LOCKS: Arc>> = Arc::new(RwLock::new(HashMap::new())); - static ref MAX_WAIT: Arc>> = - Arc::new(Mutex::new(RefCell::new(Duration::from_secs(60)))); static ref MUTEX_ID: Arc = Arc::new(AtomicU32::new(1)); } +#[cfg(feature = "timeout")] +lazy_static! { + static ref MAX_WAIT: Arc> = Arc::new(RwLock::new(Duration::from_secs(60))); +} + impl Default for UniqueReentrantMutex { fn default() -> Self { Self { @@ -67,20 +69,23 @@ impl Default for UniqueReentrantMutex { /// /// 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.lock().replace(max_wait); + *MAX_WAIT.write() = max_wait; } pub(crate) fn wait_duration() -> Duration { - *MAX_WAIT.lock().borrow() + *MAX_WAIT.read() } pub(crate) fn check_new_key(name: &str) { let start = Instant::now(); loop { - #[cfg(feature = "logging")] + #[cfg(all(feature = "logging", feature = "timeout"))] { - let duration = Instant::now() - start; + let duration = start.elapsed(); debug!("Waiting for '{}' {:?}", name, duration); } // Check if a new key is needed. Just need a read lock, which can be done in sync with everyone else @@ -105,9 +110,12 @@ pub(crate) fn check_new_key(name: &str) { // If the try_lock fails, then go around the loop again // Odds are another test was also locking on the write and has now written the key - let duration = Instant::now() - start; - if duration >= wait_duration() { - panic!("check_new_key timed out!"); + #[cfg(feature = "timeout")] + { + let duration = start.elapsed(); + if duration > wait_duration() { + panic!("Timeout waiting for '{}' {:?}", name, duration); + } } } } From ed9a8d1f27a70d9921fc1f121f1b60adabb3c6a8 Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Fri, 1 Jul 2022 12:20:50 +0200 Subject: [PATCH 2/3] Fix indefinitely spelling Signed-off-by: Heinz N. Gies --- serial_test/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/serial_test/Cargo.toml b/serial_test/Cargo.toml index 525feed..23bd311 100644 --- a/serial_test/Cargo.toml +++ b/serial_test/Cargo.toml @@ -35,7 +35,7 @@ logging = ["log"] file_locks = ["fslock"] ## The `timeout` feature lets tests time out after a certain amount of time -## if not enabled tests will wait indefinetly to be started +## if not enabled tests will wait indefinitely to be started timeout = [] docsrs = ["document-features"] From e517367b32f29333728650b03a9d84657f72e36e Mon Sep 17 00:00:00 2001 From: "Heinz N. Gies" Date: Fri, 1 Jul 2022 12:26:58 +0200 Subject: [PATCH 3/3] Fix missing cfg's Signed-off-by: Heinz N. Gies --- serial_test/src/code_lock.rs | 6 +++++- serial_test/src/lib.rs | 1 + serial_test/src/serial_code_lock.rs | 9 +++++---- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/serial_test/src/code_lock.rs b/serial_test/src/code_lock.rs index ec0f24d..48e2128 100644 --- a/serial_test/src/code_lock.rs +++ b/serial_test/src/code_lock.rs @@ -3,11 +3,13 @@ use lazy_static::lazy_static; #[cfg(feature = "logging")] use log::debug; use parking_lot::RwLock; +#[cfg(feature = "timeout")] +use std::time::Instant; use std::{ collections::HashMap, ops::{Deref, DerefMut}, sync::{atomic::AtomicU32, Arc}, - time::{Duration, Instant}, + time::Duration, }; pub(crate) struct UniqueReentrantMutex { @@ -76,11 +78,13 @@ 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")] let start = Instant::now(); loop { #[cfg(all(feature = "logging", feature = "timeout"))] diff --git a/serial_test/src/lib.rs b/serial_test/src/lib.rs index 00032fa..28e9abc 100644 --- a/serial_test/src/lib.rs +++ b/serial_test/src/lib.rs @@ -63,6 +63,7 @@ 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, diff --git a/serial_test/src/serial_code_lock.rs b/serial_test/src/serial_code_lock.rs index 6c80687..5c494bd 100644 --- a/serial_test/src/serial_code_lock.rs +++ b/serial_test/src/serial_code_lock.rs @@ -53,13 +53,14 @@ pub async fn local_async_serial_core(name: &str, fut: impl std::future::Future