summaryrefslogtreecommitdiff
path: root/tests/evil_try_mutex.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tests/evil_try_mutex.rs')
-rw-r--r--tests/evil_try_mutex.rs81
1 files changed, 81 insertions, 0 deletions
diff --git a/tests/evil_try_mutex.rs b/tests/evil_try_mutex.rs
new file mode 100644
index 0000000..5c31a91
--- /dev/null
+++ b/tests/evil_try_mutex.rs
@@ -0,0 +1,81 @@
+use std::sync::Arc;
+
+use happylock::{
+ collection::{BoxedLockCollection, RetryingLockCollection},
+ mutex::Mutex,
+ 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) {
+ self.inner.lock()
+ }
+
+ fn try_lock(&self) -> bool {
+ panic!("mwahahahaha");
+ }
+
+ unsafe fn unlock(&self) {
+ self.inner.unlock()
+ }
+}
+
+#[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 key = ThreadKey::get().unwrap();
+ let collection = BoxedLockCollection::try_new((&*c_good, &*c_evil, &*c_useless)).unwrap();
+ let g = collection.try_lock(key);
+ println!("{}", g.unwrap().1);
+ })
+ .join();
+
+ assert!(r.is_err());
+ assert!(good_mutex.scoped_try_lock(&mut key, |_| {}).is_ok());
+ assert!(evil_mutex.scoped_try_lock(&mut key, |_| {}).is_err());
+ assert!(useless_mutex.scoped_try_lock(&mut key, |_| {}).is_ok());
+}
+
+#[test]
+fn retrying_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 key = ThreadKey::get().unwrap();
+ let collection =
+ RetryingLockCollection::try_new((&*c_good, &*c_evil, &*c_useless)).unwrap();
+ let _ = collection.try_lock(key);
+ })
+ .join();
+
+ assert!(r.is_err());
+ assert!(good_mutex.scoped_try_lock(&mut key, |_| {}).is_ok());
+ assert!(evil_mutex.scoped_try_lock(&mut key, |_| {}).is_err());
+ assert!(useless_mutex.scoped_try_lock(&mut key, |_| {}).is_ok());
+}