diff options
| author | Connor Tsui <connor.tsui20@gmail.com> | 2025-07-23 14:04:32 +0200 |
|---|---|---|
| committer | Connor Tsui <connor.tsui20@gmail.com> | 2025-07-29 10:33:05 +0200 |
| commit | f34fb05923ab4c8bff48bf5d52ca08c5b8e2233a (patch) | |
| tree | 06ab4a5e52b4bd34aefa6030e8d8c6c5f6fafc83 /library | |
| parent | 3bdc228c103d72a61d9639d6fd0dd5c1566ec37f (diff) | |
| download | rust-f34fb05923ab4c8bff48bf5d52ca08c5b8e2233a.tar.gz rust-f34fb05923ab4c8bff48bf5d52ca08c5b8e2233a.zip | |
reorder mutex tests
This commit simply helps discern the actual changes needed to test both poison and nonpoison locks.
Diffstat (limited to 'library')
| -rw-r--r-- | library/std/tests/sync/mutex.rs | 302 |
1 files changed, 158 insertions, 144 deletions
diff --git a/library/std/tests/sync/mutex.rs b/library/std/tests/sync/mutex.rs index ac82914d6de..6f06d3385d1 100644 --- a/library/std/tests/sync/mutex.rs +++ b/library/std/tests/sync/mutex.rs @@ -6,28 +6,9 @@ use std::sync::mpsc::channel; use std::sync::{Arc, Condvar, MappedMutexGuard, Mutex, MutexGuard, TryLockError}; use std::{hint, mem, thread}; -struct Packet<T>(Arc<(Mutex<T>, Condvar)>); - -#[derive(Eq, PartialEq, Debug)] -struct NonCopy(i32); - -#[derive(Eq, PartialEq, Debug)] -struct NonCopyNeedsDrop(i32); - -impl Drop for NonCopyNeedsDrop { - fn drop(&mut self) { - hint::black_box(()); - } -} - -#[test] -fn test_needs_drop() { - assert!(!mem::needs_drop::<NonCopy>()); - assert!(mem::needs_drop::<NonCopyNeedsDrop>()); -} - -#[derive(Clone, Eq, PartialEq, Debug)] -struct Cloneable(i32); +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Nonpoison & Poison Tests +//////////////////////////////////////////////////////////////////////////////////////////////////// #[test] fn smoke() { @@ -78,19 +59,22 @@ fn try_lock() { *m.try_lock().unwrap() = (); } -fn new_poisoned_mutex<T>(value: T) -> Mutex<T> { - let mutex = Mutex::new(value); - - let catch_unwind_result = panic::catch_unwind(AssertUnwindSafe(|| { - let _guard = mutex.lock().unwrap(); +#[derive(Eq, PartialEq, Debug)] +struct NonCopy(i32); - panic!("test panic to poison mutex"); - })); +#[derive(Eq, PartialEq, Debug)] +struct NonCopyNeedsDrop(i32); - assert!(catch_unwind_result.is_err()); - assert!(mutex.is_poisoned()); +impl Drop for NonCopyNeedsDrop { + fn drop(&mut self) { + hint::black_box(()); + } +} - mutex +#[test] +fn test_needs_drop() { + assert!(!mem::needs_drop::<NonCopy>()); + assert!(mem::needs_drop::<NonCopyNeedsDrop>()); } #[test] @@ -118,6 +102,143 @@ fn test_into_inner_drop() { } #[test] +fn test_get_mut() { + let mut m = Mutex::new(NonCopy(10)); + *m.get_mut().unwrap() = NonCopy(20); + assert_eq!(m.into_inner().unwrap(), NonCopy(20)); +} + +#[test] +fn test_get_cloned() { + #[derive(Clone, Eq, PartialEq, Debug)] + struct Cloneable(i32); + + let m = Mutex::new(Cloneable(10)); + + assert_eq!(m.get_cloned().unwrap(), Cloneable(10)); +} + +#[test] +fn test_set() { + fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T) + where + T: Debug + Eq, + { + let m = Mutex::new(init()); + + assert_eq!(*m.lock().unwrap(), init()); + m.set(value()).unwrap(); + assert_eq!(*m.lock().unwrap(), value()); + } + + inner(|| NonCopy(10), || NonCopy(20)); + inner(|| NonCopyNeedsDrop(10), || NonCopyNeedsDrop(20)); +} + +#[test] +fn test_replace() { + fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T) + where + T: Debug + Eq, + { + let m = Mutex::new(init()); + + assert_eq!(*m.lock().unwrap(), init()); + assert_eq!(m.replace(value()).unwrap(), init()); + assert_eq!(*m.lock().unwrap(), value()); + } + + inner(|| NonCopy(10), || NonCopy(20)); + inner(|| NonCopyNeedsDrop(10), || NonCopyNeedsDrop(20)); +} + +#[test] +fn test_mutex_arc_condvar() { + struct Packet<T>(Arc<(Mutex<T>, Condvar)>); + + let packet = Packet(Arc::new((Mutex::new(false), Condvar::new()))); + let packet2 = Packet(packet.0.clone()); + let (tx, rx) = channel(); + let _t = thread::spawn(move || { + // wait until parent gets in + rx.recv().unwrap(); + let &(ref lock, ref cvar) = &*packet2.0; + let mut lock = lock.lock().unwrap(); + *lock = true; + cvar.notify_one(); + }); + + let &(ref lock, ref cvar) = &*packet.0; + let mut lock = lock.lock().unwrap(); + tx.send(()).unwrap(); + assert!(!*lock); + while !*lock { + lock = cvar.wait(lock).unwrap(); + } +} + +#[test] +fn test_mutex_arc_nested() { + // Tests nested mutexes and access + // to underlying data. + let arc = Arc::new(Mutex::new(1)); + let arc2 = Arc::new(Mutex::new(arc)); + let (tx, rx) = channel(); + let _t = thread::spawn(move || { + let lock = arc2.lock().unwrap(); + let lock2 = lock.lock().unwrap(); + assert_eq!(*lock2, 1); + tx.send(()).unwrap(); + }); + rx.recv().unwrap(); +} + +#[test] +fn test_mutex_unsized() { + let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]); + { + let b = &mut *mutex.lock().unwrap(); + b[0] = 4; + b[2] = 5; + } + 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]); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Poison Tests +//////////////////////////////////////////////////////////////////////////////////////////////////// + +/// Creates a mutex that is immediately poisoned. +fn new_poisoned_mutex<T>(value: T) -> Mutex<T> { + let mutex = Mutex::new(value); + + let catch_unwind_result = panic::catch_unwind(AssertUnwindSafe(|| { + let _guard = mutex.lock().unwrap(); + + panic!("test panic to poison mutex"); + })); + + assert!(catch_unwind_result.is_err()); + assert!(mutex.is_poisoned()); + + mutex +} + +#[test] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_into_inner_poison() { let m = new_poisoned_mutex(NonCopy(10)); @@ -129,15 +250,11 @@ fn test_into_inner_poison() { } #[test] -fn test_get_cloned() { - let m = Mutex::new(Cloneable(10)); - - assert_eq!(m.get_cloned().unwrap(), Cloneable(10)); -} - -#[test] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_get_cloned_poison() { + #[derive(Clone, Eq, PartialEq, Debug)] + struct Cloneable(i32); + let m = new_poisoned_mutex(Cloneable(10)); match m.get_cloned() { @@ -147,13 +264,6 @@ fn test_get_cloned_poison() { } #[test] -fn test_get_mut() { - let mut m = Mutex::new(NonCopy(10)); - *m.get_mut().unwrap() = NonCopy(20); - assert_eq!(m.into_inner().unwrap(), NonCopy(20)); -} - -#[test] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_get_mut_poison() { let mut m = new_poisoned_mutex(NonCopy(10)); @@ -165,23 +275,6 @@ fn test_get_mut_poison() { } #[test] -fn test_set() { - fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T) - where - T: Debug + Eq, - { - let m = Mutex::new(init()); - - assert_eq!(*m.lock().unwrap(), init()); - m.set(value()).unwrap(); - assert_eq!(*m.lock().unwrap(), value()); - } - - inner(|| NonCopy(10), || NonCopy(20)); - inner(|| NonCopyNeedsDrop(10), || NonCopyNeedsDrop(20)); -} - -#[test] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_set_poison() { fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T) @@ -204,23 +297,6 @@ fn test_set_poison() { } #[test] -fn test_replace() { - fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T) - where - T: Debug + Eq, - { - let m = Mutex::new(init()); - - assert_eq!(*m.lock().unwrap(), init()); - assert_eq!(m.replace(value()).unwrap(), init()); - assert_eq!(*m.lock().unwrap(), value()); - } - - inner(|| NonCopy(10), || NonCopy(20)); - inner(|| NonCopyNeedsDrop(10), || NonCopyNeedsDrop(20)); -} - -#[test] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_replace_poison() { fn inner<T>(mut init: impl FnMut() -> T, mut value: impl FnMut() -> T) @@ -243,31 +319,10 @@ fn test_replace_poison() { } #[test] -fn test_mutex_arc_condvar() { - let packet = Packet(Arc::new((Mutex::new(false), Condvar::new()))); - let packet2 = Packet(packet.0.clone()); - let (tx, rx) = channel(); - let _t = thread::spawn(move || { - // wait until parent gets in - rx.recv().unwrap(); - let &(ref lock, ref cvar) = &*packet2.0; - let mut lock = lock.lock().unwrap(); - *lock = true; - cvar.notify_one(); - }); - - let &(ref lock, ref cvar) = &*packet.0; - let mut lock = lock.lock().unwrap(); - tx.send(()).unwrap(); - assert!(!*lock); - while !*lock { - lock = cvar.wait(lock).unwrap(); - } -} - -#[test] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_arc_condvar_poison() { + struct Packet<T>(Arc<(Mutex<T>, Condvar)>); + let packet = Packet(Arc::new((Mutex::new(1), Condvar::new()))); let packet2 = Packet(packet.0.clone()); let (tx, rx) = channel(); @@ -327,22 +382,6 @@ fn test_mutex_arc_poison_mapped() { } #[test] -fn test_mutex_arc_nested() { - // Tests nested mutexes and access - // to underlying data. - let arc = Arc::new(Mutex::new(1)); - let arc2 = Arc::new(Mutex::new(arc)); - let (tx, rx) = channel(); - let _t = thread::spawn(move || { - let lock = arc2.lock().unwrap(); - let lock2 = lock.lock().unwrap(); - assert_eq!(*lock2, 1); - tx.send(()).unwrap(); - }); - rx.recv().unwrap(); -} - -#[test] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_mutex_arc_access_in_unwind() { let arc = Arc::new(Mutex::new(1)); @@ -365,31 +404,6 @@ fn test_mutex_arc_access_in_unwind() { } #[test] -fn test_mutex_unsized() { - let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]); - { - let b = &mut *mutex.lock().unwrap(); - b[0] = 4; - b[2] = 5; - } - 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]); -} - -#[test] #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn panic_while_mapping_unlocked_poison() { let lock = Mutex::new(()); |
