]> git.proxmox.com Git - rustc.git/blobdiff - vendor/crossbeam-queue/tests/seg_queue.rs
Merge tag 'debian/1.52.1+dfsg1-1_exp2' into proxmox/buster
[rustc.git] / vendor / crossbeam-queue / tests / seg_queue.rs
diff --git a/vendor/crossbeam-queue/tests/seg_queue.rs b/vendor/crossbeam-queue/tests/seg_queue.rs
new file mode 100644 (file)
index 0000000..ec32e1f
--- /dev/null
@@ -0,0 +1,167 @@
+extern crate crossbeam_queue;
+extern crate crossbeam_utils;
+extern crate rand;
+
+use std::sync::atomic::{AtomicUsize, Ordering};
+
+use crossbeam_queue::SegQueue;
+use crossbeam_utils::thread::scope;
+use rand::{thread_rng, Rng};
+
+#[test]
+fn smoke() {
+    let q = SegQueue::new();
+    q.push(7);
+    assert_eq!(q.pop(), Ok(7));
+
+    q.push(8);
+    assert_eq!(q.pop(), Ok(8));
+    assert!(q.pop().is_err());
+}
+
+#[test]
+fn len_empty_full() {
+    let q = SegQueue::new();
+
+    assert_eq!(q.len(), 0);
+    assert_eq!(q.is_empty(), true);
+
+    q.push(());
+
+    assert_eq!(q.len(), 1);
+    assert_eq!(q.is_empty(), false);
+
+    q.pop().unwrap();
+
+    assert_eq!(q.len(), 0);
+    assert_eq!(q.is_empty(), true);
+}
+
+#[test]
+fn len() {
+    let q = SegQueue::new();
+
+    assert_eq!(q.len(), 0);
+
+    for i in 0..50 {
+        q.push(i);
+        assert_eq!(q.len(), i + 1);
+    }
+
+    for i in 0..50 {
+        q.pop().unwrap();
+        assert_eq!(q.len(), 50 - i - 1);
+    }
+
+    assert_eq!(q.len(), 0);
+}
+
+#[test]
+fn spsc() {
+    const COUNT: usize = 100_000;
+
+    let q = SegQueue::new();
+
+    scope(|scope| {
+        scope.spawn(|_| {
+            for i in 0..COUNT {
+                loop {
+                    if let Ok(x) = q.pop() {
+                        assert_eq!(x, i);
+                        break;
+                    }
+                }
+            }
+            assert!(q.pop().is_err());
+        });
+        scope.spawn(|_| {
+            for i in 0..COUNT {
+                q.push(i);
+            }
+        });
+    })
+    .unwrap();
+}
+
+#[test]
+fn mpmc() {
+    const COUNT: usize = 25_000;
+    const THREADS: usize = 4;
+
+    let q = SegQueue::<usize>::new();
+    let v = (0..COUNT).map(|_| AtomicUsize::new(0)).collect::<Vec<_>>();
+
+    scope(|scope| {
+        for _ in 0..THREADS {
+            scope.spawn(|_| {
+                for _ in 0..COUNT {
+                    let n = loop {
+                        if let Ok(x) = q.pop() {
+                            break x;
+                        }
+                    };
+                    v[n].fetch_add(1, Ordering::SeqCst);
+                }
+            });
+        }
+        for _ in 0..THREADS {
+            scope.spawn(|_| {
+                for i in 0..COUNT {
+                    q.push(i);
+                }
+            });
+        }
+    })
+    .unwrap();
+
+    for c in v {
+        assert_eq!(c.load(Ordering::SeqCst), THREADS);
+    }
+}
+
+#[test]
+fn drops() {
+    static DROPS: AtomicUsize = AtomicUsize::new(0);
+
+    #[derive(Debug, PartialEq)]
+    struct DropCounter;
+
+    impl Drop for DropCounter {
+        fn drop(&mut self) {
+            DROPS.fetch_add(1, Ordering::SeqCst);
+        }
+    }
+
+    let mut rng = thread_rng();
+
+    for _ in 0..100 {
+        let steps = rng.gen_range(0, 10_000);
+        let additional = rng.gen_range(0, 1000);
+
+        DROPS.store(0, Ordering::SeqCst);
+        let q = SegQueue::new();
+
+        scope(|scope| {
+            scope.spawn(|_| {
+                for _ in 0..steps {
+                    while q.pop().is_err() {}
+                }
+            });
+
+            scope.spawn(|_| {
+                for _ in 0..steps {
+                    q.push(DropCounter);
+                }
+            });
+        })
+        .unwrap();
+
+        for _ in 0..additional {
+            q.push(DropCounter);
+        }
+
+        assert_eq!(DROPS.load(Ordering::SeqCst), steps);
+        drop(q);
+        assert_eq!(DROPS.load(Ordering::SeqCst), steps + additional);
+    }
+}