about summary refs log tree commit diff
diff options
context:
space:
mode:
authorConnor Tsui <connor.tsui20@gmail.com>2025-08-23 09:15:33 -0400
committerConnor Tsui <connor.tsui20@gmail.com>2025-08-23 09:20:44 -0400
commitb2380d2bcc429b1ac8d800bc2fdce90de81d1454 (patch)
treea2c917cc3dba42a14dc01fb577854119f49208f8
parenteaf7fd2fed70cac9ca6d75d011e1d11554c8ef5b (diff)
downloadrust-b2380d2bcc429b1ac8d800bc2fdce90de81d1454.tar.gz
rust-b2380d2bcc429b1ac8d800bc2fdce90de81d1454.zip
add nonpoison and poison condvar tests
Adds tests for the `nonpoison::Mutex` variant by using a macro to
duplicate the existing `poison` tests.

Note that all of the tests here are adapted from the existing `poison`
tests.

Also steals the `test_mutex_arc_condvar` test from `mutex.rs`.

Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
-rw-r--r--library/std/tests/sync/condvar.rs401
-rw-r--r--library/std/tests/sync/lib.rs1
-rw-r--r--library/std/tests/sync/mutex.rs34
3 files changed, 241 insertions, 195 deletions
diff --git a/library/std/tests/sync/condvar.rs b/library/std/tests/sync/condvar.rs
index 834de6bb1c2..1d712a64300 100644
--- a/library/std/tests/sync/condvar.rs
+++ b/library/std/tests/sync/condvar.rs
@@ -1,190 +1,269 @@
+use std::sync::Arc;
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::mpsc::channel;
-use std::sync::{Arc, Condvar, Mutex};
 use std::thread;
 use std::time::Duration;
 
-#[test]
-fn smoke() {
-    let c = Condvar::new();
-    c.notify_one();
-    c.notify_all();
-}
+use super::nonpoison_and_poison_unwrap_test;
+
+nonpoison_and_poison_unwrap_test!(
+    name: smoke,
+    test_body: {
+        use locks::Condvar;
+
+        let c = Condvar::new();
+        c.notify_one();
+        c.notify_all();
+    }
+);
 
-#[test]
-#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
-fn notify_one() {
-    let m = Arc::new(Mutex::new(()));
-    let m2 = m.clone();
-    let c = Arc::new(Condvar::new());
-    let c2 = c.clone();
-
-    let g = m.lock().unwrap();
-    let _t = thread::spawn(move || {
-        let _g = m2.lock().unwrap();
-        c2.notify_one();
-    });
-    let g = c.wait(g).unwrap();
-    drop(g);
-}
-
-#[test]
 #[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
-fn notify_all() {
-    const N: usize = 10;
-
-    let data = Arc::new((Mutex::new(0), Condvar::new()));
-    let (tx, rx) = channel();
-    for _ in 0..N {
-        let data = data.clone();
-        let tx = tx.clone();
-        thread::spawn(move || {
-            let &(ref lock, ref cond) = &*data;
-            let mut cnt = lock.lock().unwrap();
-            *cnt += 1;
-            if *cnt == N {
-                tx.send(()).unwrap();
-            }
-            while *cnt != 0 {
-                cnt = cond.wait(cnt).unwrap();
-            }
-            tx.send(()).unwrap();
+nonpoison_and_poison_unwrap_test!(
+    name: notify_one,
+    test_body: {
+        use locks::{Condvar, Mutex};
+
+        let m = Arc::new(Mutex::new(()));
+        let m2 = m.clone();
+        let c = Arc::new(Condvar::new());
+        let c2 = c.clone();
+
+        let g = maybe_unwrap(m.lock());
+        let _t = thread::spawn(move || {
+            let _g = maybe_unwrap(m2.lock());
+            c2.notify_one();
         });
+        let g = maybe_unwrap(c.wait(g));
+        drop(g);
     }
-    drop(tx);
+);
 
-    let &(ref lock, ref cond) = &*data;
-    rx.recv().unwrap();
-    let mut cnt = lock.lock().unwrap();
-    *cnt = 0;
-    cond.notify_all();
-    drop(cnt);
+#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
+nonpoison_and_poison_unwrap_test!(
+    name: notify_all,
+    test_body: {
+        use locks::{Condvar, Mutex};
+
+        const N: usize = 10;
 
-    for _ in 0..N {
+        let data = Arc::new((Mutex::new(0), Condvar::new()));
+        let (tx, rx) = channel();
+        for _ in 0..N {
+            let data = data.clone();
+            let tx = tx.clone();
+            thread::spawn(move || {
+                let &(ref lock, ref cond) = &*data;
+                let mut cnt = maybe_unwrap(lock.lock());
+                *cnt += 1;
+                if *cnt == N {
+                    tx.send(()).unwrap();
+                }
+                while *cnt != 0 {
+                    cnt = maybe_unwrap(cond.wait(cnt));
+                }
+                tx.send(()).unwrap();
+            });
+        }
+        drop(tx);
+
+        let &(ref lock, ref cond) = &*data;
         rx.recv().unwrap();
+        let mut cnt = maybe_unwrap(lock.lock());
+        *cnt = 0;
+        cond.notify_all();
+        drop(cnt);
+
+        for _ in 0..N {
+            rx.recv().unwrap();
+        }
     }
-}
+);
 
-#[test]
 #[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
-fn wait_while() {
-    let pair = Arc::new((Mutex::new(false), Condvar::new()));
-    let pair2 = pair.clone();
-
-    // Inside of our lock, spawn a new thread, and then wait for it to start.
-    thread::spawn(move || {
-        let &(ref lock, ref cvar) = &*pair2;
-        let mut started = lock.lock().unwrap();
-        *started = true;
-        // We notify the condvar that the value has changed.
-        cvar.notify_one();
-    });
-
-    // Wait for the thread to start up.
-    let &(ref lock, ref cvar) = &*pair;
-    let guard = cvar.wait_while(lock.lock().unwrap(), |started| !*started);
-    assert!(*guard.unwrap());
-}
-
-#[test]
-#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // condvar wait not supported
-fn wait_timeout_wait() {
-    let m = Arc::new(Mutex::new(()));
-    let c = Arc::new(Condvar::new());
-
-    loop {
-        let g = m.lock().unwrap();
-        let (_g, no_timeout) = c.wait_timeout(g, Duration::from_millis(1)).unwrap();
-        // spurious wakeups mean this isn't necessarily true
-        // so execute test again, if not timeout
-        if !no_timeout.timed_out() {
-            continue;
+nonpoison_and_poison_unwrap_test!(
+    name: test_mutex_arc_condvar,
+    test_body: {
+        use locks::{Condvar, Mutex};
+
+        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 our parent has taken the lock.
+            rx.recv().unwrap();
+            let &(ref lock, ref cvar) = &*packet2.0;
+
+            // Set the data to `true` and wake up our parent.
+            let mut guard = maybe_unwrap(lock.lock());
+            *guard = true;
+            cvar.notify_one();
+        });
+
+        let &(ref lock, ref cvar) = &*packet.0;
+        let mut guard = maybe_unwrap(lock.lock());
+        // Wake up our child.
+        tx.send(()).unwrap();
+
+        // Wait until our child has set the data to `true`.
+        assert!(!*guard);
+        while !*guard {
+            guard = maybe_unwrap(cvar.wait(guard));
         }
+    }
+);
+
+#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
+nonpoison_and_poison_unwrap_test!(
+    name: wait_while,
+    test_body: {
+        use locks::{Condvar, Mutex};
+
+        let pair = Arc::new((Mutex::new(false), Condvar::new()));
+        let pair2 = pair.clone();
 
-        break;
+        // Inside of our lock, spawn a new thread, and then wait for it to start.
+        thread::spawn(move || {
+            let &(ref lock, ref cvar) = &*pair2;
+            let mut started = maybe_unwrap(lock.lock());
+            *started = true;
+            // We notify the condvar that the value has changed.
+            cvar.notify_one();
+        });
+
+        // Wait for the thread to start up.
+        let &(ref lock, ref cvar) = &*pair;
+        let guard = cvar.wait_while(maybe_unwrap(lock.lock()), |started| !*started);
+        assert!(*maybe_unwrap(guard));
     }
-}
-
-#[test]
-#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // condvar wait not supported
-fn wait_timeout_while_wait() {
-    let m = Arc::new(Mutex::new(()));
-    let c = Arc::new(Condvar::new());
-
-    let g = m.lock().unwrap();
-    let (_g, wait) = c.wait_timeout_while(g, Duration::from_millis(1), |_| true).unwrap();
-    // no spurious wakeups. ensure it timed-out
-    assert!(wait.timed_out());
-}
-
-#[test]
-#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // condvar wait not supported
-fn wait_timeout_while_instant_satisfy() {
-    let m = Arc::new(Mutex::new(()));
-    let c = Arc::new(Condvar::new());
-
-    let g = m.lock().unwrap();
-    let (_g, wait) = c.wait_timeout_while(g, Duration::from_millis(0), |_| false).unwrap();
-    // ensure it didn't time-out even if we were not given any time.
-    assert!(!wait.timed_out());
-}
-
-#[test]
+);
+
 #[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
-fn wait_timeout_while_wake() {
-    let pair = Arc::new((Mutex::new(false), Condvar::new()));
-    let pair_copy = pair.clone();
-
-    let &(ref m, ref c) = &*pair;
-    let g = m.lock().unwrap();
-    let _t = thread::spawn(move || {
-        let &(ref lock, ref cvar) = &*pair_copy;
-        let mut started = lock.lock().unwrap();
-        thread::sleep(Duration::from_millis(1));
-        *started = true;
-        cvar.notify_one();
-    });
-    let (g2, wait) = c
-        .wait_timeout_while(g, Duration::from_millis(u64::MAX), |&mut notified| !notified)
-        .unwrap();
-    // ensure it didn't time-out even if we were not given any time.
-    assert!(!wait.timed_out());
-    assert!(*g2);
-}
-
-#[test]
+nonpoison_and_poison_unwrap_test!(
+    name: wait_timeout_wait,
+    test_body: {
+        use locks::{Condvar, Mutex};
+
+        let m = Arc::new(Mutex::new(()));
+        let c = Arc::new(Condvar::new());
+
+        loop {
+            let g = maybe_unwrap(m.lock());
+            let (_g, no_timeout) = maybe_unwrap(c.wait_timeout(g, Duration::from_millis(1)));
+            // spurious wakeups mean this isn't necessarily true
+            // so execute test again, if not timeout
+            if !no_timeout.timed_out() {
+                continue;
+            }
+
+            break;
+        }
+    }
+);
+
 #[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
-fn wait_timeout_wake() {
-    let m = Arc::new(Mutex::new(()));
-    let c = Arc::new(Condvar::new());
+nonpoison_and_poison_unwrap_test!(
+    name: wait_timeout_while_wait,
+    test_body: {
+        use locks::{Condvar, Mutex};
 
-    loop {
-        let g = m.lock().unwrap();
+        let m = Arc::new(Mutex::new(()));
+        let c = Arc::new(Condvar::new());
 
-        let c2 = c.clone();
-        let m2 = m.clone();
+        let g = maybe_unwrap(m.lock());
+        let (_g, wait) = maybe_unwrap(c.wait_timeout_while(g, Duration::from_millis(1), |_| true));
+        // no spurious wakeups. ensure it timed-out
+        assert!(wait.timed_out());
+    }
+);
+
+#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
+nonpoison_and_poison_unwrap_test!(
+    name: wait_timeout_while_instant_satisfy,
+    test_body: {
+        use locks::{Condvar, Mutex};
+
+        let m = Arc::new(Mutex::new(()));
+        let c = Arc::new(Condvar::new());
+
+        let g = maybe_unwrap(m.lock());
+        let (_g, wait) =
+            maybe_unwrap(c.wait_timeout_while(g, Duration::from_millis(0), |_| false));
+        // ensure it didn't time-out even if we were not given any time.
+        assert!(!wait.timed_out());
+    }
+);
 
-        let notified = Arc::new(AtomicBool::new(false));
-        let notified_copy = notified.clone();
+#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
+nonpoison_and_poison_unwrap_test!(
+    name: wait_timeout_while_wake,
+    test_body: {
+        use locks::{Condvar, Mutex};
+
+        let pair = Arc::new((Mutex::new(false), Condvar::new()));
+        let pair_copy = pair.clone();
 
-        let t = thread::spawn(move || {
-            let _g = m2.lock().unwrap();
+        let &(ref m, ref c) = &*pair;
+        let g = maybe_unwrap(m.lock());
+        let _t = thread::spawn(move || {
+            let &(ref lock, ref cvar) = &*pair_copy;
+            let mut started = maybe_unwrap(lock.lock());
             thread::sleep(Duration::from_millis(1));
-            notified_copy.store(true, Ordering::Relaxed);
-            c2.notify_one();
+            *started = true;
+            cvar.notify_one();
         });
-        let (g, timeout_res) = c.wait_timeout(g, Duration::from_millis(u64::MAX)).unwrap();
-        assert!(!timeout_res.timed_out());
-        // spurious wakeups mean this isn't necessarily true
-        // so execute test again, if not notified
-        if !notified.load(Ordering::Relaxed) {
-            t.join().unwrap();
-            continue;
-        }
-        drop(g);
+        let (g2, wait) = maybe_unwrap(c.wait_timeout_while(
+            g,
+            Duration::from_millis(u64::MAX),
+            |&mut notified| !notified
+        ));
+        // ensure it didn't time-out even if we were not given any time.
+        assert!(!wait.timed_out());
+        assert!(*g2);
+    }
+);
+
+#[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
+nonpoison_and_poison_unwrap_test!(
+    name: wait_timeout_wake,
+    test_body: {
+        use locks::{Condvar, Mutex};
 
-        t.join().unwrap();
+        let m = Arc::new(Mutex::new(()));
+        let c = Arc::new(Condvar::new());
 
-        break;
+        loop {
+            let g = maybe_unwrap(m.lock());
+
+            let c2 = c.clone();
+            let m2 = m.clone();
+
+            let notified = Arc::new(AtomicBool::new(false));
+            let notified_copy = notified.clone();
+
+            let t = thread::spawn(move || {
+                let _g = maybe_unwrap(m2.lock());
+                thread::sleep(Duration::from_millis(1));
+                notified_copy.store(true, Ordering::Relaxed);
+                c2.notify_one();
+            });
+            let (g, timeout_res) =
+                maybe_unwrap(c.wait_timeout(g, Duration::from_millis(u64::MAX)));
+            assert!(!timeout_res.timed_out());
+            // spurious wakeups mean this isn't necessarily true
+            // so execute test again, if not notified
+            if !notified.load(Ordering::Relaxed) {
+                t.join().unwrap();
+                continue;
+            }
+            drop(g);
+
+            t.join().unwrap();
+
+            break;
+        }
     }
-}
+);
diff --git a/library/std/tests/sync/lib.rs b/library/std/tests/sync/lib.rs
index f874c2ba389..ac1dbebcc5c 100644
--- a/library/std/tests/sync/lib.rs
+++ b/library/std/tests/sync/lib.rs
@@ -7,6 +7,7 @@
 #![feature(rwlock_downgrade)]
 #![feature(std_internals)]
 #![feature(sync_nonpoison)]
+#![feature(nonpoison_condvar)]
 #![feature(nonpoison_mutex)]
 #![feature(nonpoison_rwlock)]
 #![allow(internal_features)]
diff --git a/library/std/tests/sync/mutex.rs b/library/std/tests/sync/mutex.rs
index 90cefc0d594..612c75c7aef 100644
--- a/library/std/tests/sync/mutex.rs
+++ b/library/std/tests/sync/mutex.rs
@@ -213,40 +213,6 @@ nonpoison_and_poison_unwrap_test!(
     }
 );
 
-// FIXME(nonpoison_condvar): Move this to the `condvar.rs` test file once `nonpoison::condvar` gets
-// implemented.
-#[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 our parent has taken the lock.
-        rx.recv().unwrap();
-        let &(ref lock, ref cvar) = &*packet2.0;
-
-        // Set the data to `true` and wake up our parent.
-        let mut guard = lock.lock().unwrap();
-        *guard = true;
-        cvar.notify_one();
-    });
-
-    let &(ref lock, ref cvar) = &*packet.0;
-    let mut guard = lock.lock().unwrap();
-    // Wake up our child.
-    tx.send(()).unwrap();
-
-    // Wait until our child has set the data to `true`.
-    assert!(!*guard);
-    while !*guard {
-        guard = cvar.wait(guard).unwrap();
-    }
-}
-
 nonpoison_and_poison_unwrap_test!(
     name: test_mutex_arc_nested,
     test_body: {