diff options
| author | Mica White <botahamec@gmail.com> | 2024-12-23 15:33:14 -0500 |
|---|---|---|
| committer | Mica White <botahamec@gmail.com> | 2024-12-24 20:23:53 -0500 |
| commit | 7e2a3aa417beb33c76fe98fbe49515c524cb0183 (patch) | |
| tree | 7c54f6012b731c1b59f8d13923a789f72824457a | |
| parent | 30d0f08b6073e9c2e545a3567838a9e1e885fea2 (diff) | |
Unit test mutex death
| -rw-r--r-- | Cargo.toml | 3 | ||||
| -rw-r--r-- | tests/evil_mutex.rs | 54 | ||||
| -rw-r--r-- | tests/evil_rwlock.rs | 66 |
3 files changed, 123 insertions, 0 deletions
@@ -21,5 +21,8 @@ spin = { version = "0.9", optional = true } mutants = "0.0.3" # used to skip functions that can't run +[dev-dependencies] +parking_lot = "0.12" + [features] default = ["parking_lot"] diff --git a/tests/evil_mutex.rs b/tests/evil_mutex.rs new file mode 100644 index 0000000..510ee3f --- /dev/null +++ b/tests/evil_mutex.rs @@ -0,0 +1,54 @@ +use std::sync::Arc; + +use happylock::collection::BoxedLockCollection; +use happylock::mutex::Mutex; +use happylock::ThreadKey; +use lock_api::{GuardNoSend, RawMutex}; + +struct EvilMutex { + inner: parking_lot::RawMutex, +} + +unsafe impl RawMutex for EvilMutex { + #[allow(clippy::declare_interior_mutable_const)] + const INIT: Self = Self { + inner: parking_lot::RawMutex::INIT, + }; + + type GuardMarker = GuardNoSend; + + fn lock(&self) { + panic!("mwahahahaha"); + } + + fn try_lock(&self) -> bool { + self.inner.try_lock() + } + + unsafe fn unlock(&self) { + panic!("mwahahahaha"); + } +} + +#[test] +fn boxed_mutexes() { + let mut key = ThreadKey::get().unwrap(); + let good_mutex: Arc<Mutex<i32, parking_lot::RawMutex>> = Arc::new(Mutex::new(5)); + let evil_mutex: Arc<Mutex<i32, EvilMutex>> = Arc::new(Mutex::new(7)); + let useless_mutex: Arc<Mutex<i32, parking_lot::RawMutex>> = Arc::new(Mutex::new(10)); + let c_good = Arc::clone(&good_mutex); + let c_evil = Arc::clone(&evil_mutex); + let c_useless = Arc::clone(&useless_mutex); + + let r = std::thread::spawn(move || { + let mut key = ThreadKey::get().unwrap(); + let collection = BoxedLockCollection::try_new((&*c_good, &*c_evil, &*c_useless)).unwrap(); + collection.lock(&mut key); + }) + .join(); + + assert!(r.is_err()); + assert!(good_mutex.try_lock(&mut key).is_some()); + assert!(evil_mutex.try_lock(&mut key).is_none()); + assert!(useless_mutex.try_lock(&mut key).is_some()); +} diff --git a/tests/evil_rwlock.rs b/tests/evil_rwlock.rs new file mode 100644 index 0000000..b4fbc52 --- /dev/null +++ b/tests/evil_rwlock.rs @@ -0,0 +1,66 @@ +use std::sync::Arc; + +use happylock::collection::BoxedLockCollection; +use happylock::rwlock::RwLock; +use happylock::ThreadKey; +use lock_api::{GuardNoSend, RawRwLock}; + +struct EvilRwLock { + inner: parking_lot::RawRwLock, +} + +unsafe impl RawRwLock for EvilRwLock { + #[allow(clippy::declare_interior_mutable_const)] + const INIT: Self = Self { + inner: parking_lot::RawRwLock::INIT, + }; + + type GuardMarker = GuardNoSend; + + fn lock_shared(&self) { + panic!("mwahahahaha"); + } + + fn try_lock_shared(&self) -> bool { + self.inner.try_lock_shared() + } + + unsafe fn unlock_shared(&self) { + panic!("mwahahahaha"); + } + + fn lock_exclusive(&self) { + panic!("mwahahahaha"); + } + + fn try_lock_exclusive(&self) -> bool { + self.inner.try_lock_exclusive() + } + + unsafe fn unlock_exclusive(&self) { + panic!("mwahahahaha"); + } +} + +#[test] +fn boxed_rwlocks() { + let mut key = ThreadKey::get().unwrap(); + let good_mutex: Arc<RwLock<i32, parking_lot::RawRwLock>> = Arc::new(RwLock::new(5)); + let evil_mutex: Arc<RwLock<i32, EvilRwLock>> = Arc::new(RwLock::new(7)); + let useless_mutex: Arc<RwLock<i32, parking_lot::RawRwLock>> = Arc::new(RwLock::new(10)); + let c_good = Arc::clone(&good_mutex); + let c_evil = Arc::clone(&evil_mutex); + let c_useless = Arc::clone(&useless_mutex); + + let r = std::thread::spawn(move || { + let mut key = ThreadKey::get().unwrap(); + let collection = BoxedLockCollection::try_new((&*c_good, &*c_evil, &*c_useless)).unwrap(); + collection.lock(&mut key); + }) + .join(); + + assert!(r.is_err()); + assert!(good_mutex.try_write(&mut key).is_some()); + assert!(evil_mutex.try_write(&mut key).is_none()); + assert!(useless_mutex.try_write(&mut key).is_some()); +} |
