1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
//! # serial_test
//! Helper crate for [serial_test_derive](../serial_test_derive/index.html)
use lazy_static::lazy_static;
use std::collections::HashMap;
use std::ops::{Deref, DerefMut};
use std::sync::{Arc, Mutex, RwLock};
lazy_static! {
static ref LOCKS: Arc<RwLock<HashMap<String, Mutex<()>>>> =
Arc::new(RwLock::new(HashMap::new()));
}
/// Helper function for [serial_test_derive::serial](../serial_test_derive/attr.serial.html)
/// ```
/// #[test]
/// fn test_serial_core() {
/// serial_core("some key", || {
/// println!("Bar");
/// });
/// }
/// ```
pub fn serial_core(name: &str, function: fn()) {
// Check if a new key is needed. Just need a read lock, which can be done in sync with everyone else
let new_key = {
let unlock = LOCKS.read().unwrap();
!unlock.deref().contains_key(name)
};
if new_key {
// This is the rare path, which avoids the multi-writer situation mostly
LOCKS
.write()
.unwrap()
.deref_mut()
.insert(name.to_string(), Mutex::new(()));
}
let unlock = LOCKS.read().unwrap();
// _guard needs to be named to avoid being instant dropped
let _guard = unlock.deref()[name].lock();
function();
}