about summary refs log tree commit diff
path: root/library/std/src/sync/condvar/tests.rs
diff options
context:
space:
mode:
authorLzu Tao <taolzu@gmail.com>2020-08-27 13:45:01 +0000
committerLzu Tao <taolzu@gmail.com>2020-08-31 02:56:59 +0000
commita4e926daeeaedc9178846711daf1f4cb6ce505fb (patch)
tree0c830f716f6f5ad17736d459f5de9b9199006d54 /library/std/src/sync/condvar/tests.rs
parentdb6cbfc49ca655739ba8caae43ebd7c77c8a1179 (diff)
downloadrust-a4e926daeeaedc9178846711daf1f4cb6ce505fb.tar.gz
rust-a4e926daeeaedc9178846711daf1f4cb6ce505fb.zip
std: move "mod tests/benches" to separate files
Also doing fmt inplace as requested.
Diffstat (limited to 'library/std/src/sync/condvar/tests.rs')
-rw-r--r--library/std/src/sync/condvar/tests.rs211
1 files changed, 211 insertions, 0 deletions
diff --git a/library/std/src/sync/condvar/tests.rs b/library/std/src/sync/condvar/tests.rs
new file mode 100644
index 00000000000..86d099ee3a1
--- /dev/null
+++ b/library/std/src/sync/condvar/tests.rs
@@ -0,0 +1,211 @@
+use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::mpsc::channel;
+use crate::sync::{Arc, Condvar, Mutex};
+use crate::thread;
+use crate::time::Duration;
+
+#[test]
+fn smoke() {
+    let c = Condvar::new();
+    c.notify_one();
+    c.notify_all();
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+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(target_os = "emscripten", ignore)]
+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();
+        });
+    }
+    drop(tx);
+
+    let &(ref lock, ref cond) = &*data;
+    rx.recv().unwrap();
+    let mut cnt = lock.lock().unwrap();
+    *cnt = 0;
+    cond.notify_all();
+    drop(cnt);
+
+    for _ in 0..N {
+        rx.recv().unwrap();
+    }
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+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(target_os = "emscripten", ignore)]
+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;
+        }
+
+        break;
+    }
+}
+
+#[test]
+#[cfg_attr(target_os = "emscripten", ignore)]
+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(target_os = "emscripten", ignore)]
+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(target_os = "emscripten", ignore)]
+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]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn wait_timeout_wake() {
+    let m = Arc::new(Mutex::new(()));
+    let c = Arc::new(Condvar::new());
+
+    loop {
+        let g = m.lock().unwrap();
+
+        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 = m2.lock().unwrap();
+            thread::sleep(Duration::from_millis(1));
+            notified_copy.store(true, Ordering::SeqCst);
+            c2.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::SeqCst) {
+            t.join().unwrap();
+            continue;
+        }
+        drop(g);
+
+        t.join().unwrap();
+
+        break;
+    }
+}
+
+#[test]
+#[should_panic]
+#[cfg_attr(target_os = "emscripten", ignore)]
+fn two_mutexes() {
+    let m = Arc::new(Mutex::new(()));
+    let m2 = m.clone();
+    let c = Arc::new(Condvar::new());
+    let c2 = c.clone();
+
+    let mut g = m.lock().unwrap();
+    let _t = thread::spawn(move || {
+        let _g = m2.lock().unwrap();
+        c2.notify_one();
+    });
+    g = c.wait(g).unwrap();
+    drop(g);
+
+    let m = Mutex::new(());
+    let _ = c.wait(m.lock().unwrap()).unwrap();
+}