Skip to content

Commit

Permalink
Add MappedMutexGuard and MappedRwLock*Guard tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
zachs18 committed Dec 5, 2023
1 parent 20fa3a0 commit 5533606
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 2 deletions.
30 changes: 29 additions & 1 deletion library/std/src/sync/mutex/tests.rs
Original file line number Diff line number Diff line change
@@ -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<T>(Arc<(Mutex<T>, Condvar)>);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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]);
}
105 changes: 104 additions & 1 deletion library/std/src/sync/rwlock/tests.rs
Original file line number Diff line number Diff line change
@@ -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;

Expand Down Expand Up @@ -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));
Expand All @@ -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));
Expand All @@ -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));
Expand All @@ -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));
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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]);
}

0 comments on commit 5533606

Please sign in to comment.