From 5533606fe0def63a62a3f75be4eb2d87081a05c4 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Tue, 24 Oct 2023 13:32:53 -0500 Subject: [PATCH] Add MappedMutexGuard and MappedRwLock*Guard tests. --- library/std/src/sync/mutex/tests.rs | 30 +++++++- library/std/src/sync/rwlock/tests.rs | 105 ++++++++++++++++++++++++++- 2 files changed, 133 insertions(+), 2 deletions(-) diff --git a/library/std/src/sync/mutex/tests.rs b/library/std/src/sync/mutex/tests.rs index 1786a3c09ffb5..cf69813baa3c5 100644 --- a/library/std/src/sync/mutex/tests.rs +++ b/library/std/src/sync/mutex/tests.rs @@ -1,6 +1,6 @@ use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sync::mpsc::channel; -use crate::sync::{Arc, Condvar, Mutex}; +use crate::sync::{Arc, Condvar, MappedMutexGuard, Mutex, MutexGuard}; use crate::thread; struct Packet(Arc<(Mutex, Condvar)>); @@ -188,6 +188,21 @@ fn test_mutex_arc_poison() { assert!(arc.is_poisoned()); } +#[test] +fn test_mutex_arc_poison_mapped() { + let arc = Arc::new(Mutex::new(1)); + assert!(!arc.is_poisoned()); + let arc2 = arc.clone(); + let _ = thread::spawn(move || { + let lock = arc2.lock().unwrap(); + let lock = MutexGuard::map(lock, |val| val); + assert_eq!(*lock, 2); // deliberate assertion failure to poison the mutex + }) + .join(); + assert!(arc.lock().is_err()); + assert!(arc.is_poisoned()); +} + #[test] fn test_mutex_arc_nested() { // Tests nested mutexes and access @@ -236,3 +251,16 @@ fn test_mutex_unsized() { let comp: &[i32] = &[4, 2, 5]; assert_eq!(&*mutex.lock().unwrap(), comp); } + +#[test] +fn test_mapping_mapped_guard() { + let arr = [0; 4]; + let mut lock = Mutex::new(arr); + let guard = lock.lock().unwrap(); + let guard = MutexGuard::map(guard, |arr| &mut arr[..2]); + let mut guard = MappedMutexGuard::map(guard, |slice| &mut slice[1..]); + assert_eq!(guard.len(), 1); + guard[0] = 42; + drop(guard); + assert_eq!(*lock.get_mut().unwrap(), [0, 42, 0, 0]); +} diff --git a/library/std/src/sync/rwlock/tests.rs b/library/std/src/sync/rwlock/tests.rs index 1a9d3d3f12f3c..0a5eb7aac023f 100644 --- a/library/std/src/sync/rwlock/tests.rs +++ b/library/std/src/sync/rwlock/tests.rs @@ -1,6 +1,9 @@ use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sync::mpsc::channel; -use crate::sync::{Arc, RwLock, RwLockReadGuard, TryLockError}; +use crate::sync::{ + Arc, MappedRwLockReadGuard, MappedRwLockWriteGuard, RwLock, RwLockReadGuard, RwLockWriteGuard, + TryLockError, +}; use crate::thread; use rand::Rng; @@ -55,6 +58,19 @@ fn test_rw_arc_poison_wr() { assert!(arc.read().is_err()); } +#[test] +fn test_rw_arc_poison_mapped_w_r() { + let arc = Arc::new(RwLock::new(1)); + let arc2 = arc.clone(); + let _: Result<(), _> = thread::spawn(move || { + let lock = arc2.write().unwrap(); + let _lock = RwLockWriteGuard::map(lock, |val| val); + panic!(); + }) + .join(); + assert!(arc.read().is_err()); +} + #[test] fn test_rw_arc_poison_ww() { let arc = Arc::new(RwLock::new(1)); @@ -69,6 +85,20 @@ fn test_rw_arc_poison_ww() { assert!(arc.is_poisoned()); } +#[test] +fn test_rw_arc_poison_mapped_w_w() { + let arc = Arc::new(RwLock::new(1)); + let arc2 = arc.clone(); + let _: Result<(), _> = thread::spawn(move || { + let lock = arc2.write().unwrap(); + let _lock = RwLockWriteGuard::map(lock, |val| val); + panic!(); + }) + .join(); + assert!(arc.write().is_err()); + assert!(arc.is_poisoned()); +} + #[test] fn test_rw_arc_no_poison_rr() { let arc = Arc::new(RwLock::new(1)); @@ -81,6 +111,21 @@ fn test_rw_arc_no_poison_rr() { let lock = arc.read().unwrap(); assert_eq!(*lock, 1); } + +#[test] +fn test_rw_arc_no_poison_mapped_r_r() { + let arc = Arc::new(RwLock::new(1)); + let arc2 = arc.clone(); + let _: Result<(), _> = thread::spawn(move || { + let lock = arc2.read().unwrap(); + let _lock = RwLockReadGuard::map(lock, |val| val); + panic!(); + }) + .join(); + let lock = arc.read().unwrap(); + assert_eq!(*lock, 1); +} + #[test] fn test_rw_arc_no_poison_rw() { let arc = Arc::new(RwLock::new(1)); @@ -94,6 +139,20 @@ fn test_rw_arc_no_poison_rw() { assert_eq!(*lock, 1); } +#[test] +fn test_rw_arc_no_poison_mapped_r_w() { + let arc = Arc::new(RwLock::new(1)); + let arc2 = arc.clone(); + let _: Result<(), _> = thread::spawn(move || { + let lock = arc2.read().unwrap(); + let _lock = RwLockReadGuard::map(lock, |val| val); + panic!(); + }) + .join(); + let lock = arc.write().unwrap(); + assert_eq!(*lock, 1); +} + #[test] fn test_rw_arc() { let arc = Arc::new(RwLock::new(0)); @@ -179,6 +238,16 @@ fn test_rwlock_try_write() { } drop(read_guard); + let mapped_read_guard = RwLockReadGuard::map(lock.read().unwrap(), |_| &()); + + let write_result = lock.try_write(); + match write_result { + Err(TryLockError::WouldBlock) => (), + Ok(_) => assert!(false, "try_write should not succeed while mapped_read_guard is in scope"), + Err(_) => assert!(false, "unexpected error"), + } + + drop(mapped_read_guard); } #[test] @@ -257,3 +326,37 @@ fn test_read_guard_covariance() { } drop(lock); } + +#[test] +fn test_mapped_read_guard_covariance() { + fn do_stuff<'a>(_: MappedRwLockReadGuard<'_, &'a i32>, _: &'a i32) {} + let j: i32 = 5; + let lock = RwLock::new((&j, &j)); + { + let i = 6; + let guard = lock.read().unwrap(); + let guard = RwLockReadGuard::map(guard, |(val, _val)| val); + do_stuff(guard, &i); + } + drop(lock); +} + +#[test] +fn test_mapping_mapped_guard() { + let arr = [0; 4]; + let mut lock = RwLock::new(arr); + let guard = lock.write().unwrap(); + let guard = RwLockWriteGuard::map(guard, |arr| &mut arr[..2]); + let mut guard = MappedRwLockWriteGuard::map(guard, |slice| &mut slice[1..]); + assert_eq!(guard.len(), 1); + guard[0] = 42; + drop(guard); + assert_eq!(*lock.get_mut().unwrap(), [0, 42, 0, 0]); + + let guard = lock.read().unwrap(); + let guard = RwLockReadGuard::map(guard, |arr| &arr[..2]); + let guard = MappedRwLockReadGuard::map(guard, |slice| &slice[1..]); + assert_eq!(*guard, [42]); + drop(guard); + assert_eq!(*lock.get_mut().unwrap(), [0, 42, 0, 0]); +}