summaryrefslogtreecommitdiffstats
path: root/third_party/rust/ringbuf/src/tests/drop.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/ringbuf/src/tests/drop.rs')
-rw-r--r--third_party/rust/ringbuf/src/tests/drop.rs240
1 files changed, 240 insertions, 0 deletions
diff --git a/third_party/rust/ringbuf/src/tests/drop.rs b/third_party/rust/ringbuf/src/tests/drop.rs
new file mode 100644
index 0000000000..54f14cf6cf
--- /dev/null
+++ b/third_party/rust/ringbuf/src/tests/drop.rs
@@ -0,0 +1,240 @@
+use crate::RingBuffer;
+use alloc::{collections::BTreeSet, vec, vec::Vec};
+use core::cell::RefCell;
+
+#[derive(Debug)]
+struct Dropper<'a> {
+ id: i32,
+ set: &'a RefCell<BTreeSet<i32>>,
+}
+
+impl<'a> Dropper<'a> {
+ fn new(set: &'a RefCell<BTreeSet<i32>>, id: i32) -> Self {
+ if !set.borrow_mut().insert(id) {
+ panic!("value {} already exists", id);
+ }
+ Self { set, id }
+ }
+}
+
+impl<'a> Drop for Dropper<'a> {
+ fn drop(&mut self) {
+ if !self.set.borrow_mut().remove(&self.id) {
+ panic!("value {} already removed", self.id);
+ }
+ }
+}
+
+#[test]
+fn single() {
+ let set = RefCell::new(BTreeSet::new());
+
+ let cap = 3;
+ let buf = RingBuffer::new(cap);
+
+ assert_eq!(set.borrow().len(), 0);
+
+ {
+ let (mut prod, mut cons) = buf.split();
+
+ prod.push(Dropper::new(&set, 1)).unwrap();
+ assert_eq!(set.borrow().len(), 1);
+ prod.push(Dropper::new(&set, 2)).unwrap();
+ assert_eq!(set.borrow().len(), 2);
+ prod.push(Dropper::new(&set, 3)).unwrap();
+ assert_eq!(set.borrow().len(), 3);
+
+ cons.pop().unwrap();
+ assert_eq!(set.borrow().len(), 2);
+ cons.pop().unwrap();
+ assert_eq!(set.borrow().len(), 1);
+
+ prod.push(Dropper::new(&set, 4)).unwrap();
+ assert_eq!(set.borrow().len(), 2);
+ }
+
+ assert_eq!(set.borrow().len(), 0);
+}
+
+#[test]
+fn multiple_each() {
+ let set = RefCell::new(BTreeSet::new());
+
+ let cap = 5;
+ let buf = RingBuffer::new(cap);
+
+ assert_eq!(set.borrow().len(), 0);
+
+ {
+ let (mut prod, mut cons) = buf.split();
+ let mut id = 0;
+ let mut cnt = 0;
+
+ assert_eq!(
+ prod.push_each(|| {
+ if cnt < 4 {
+ id += 1;
+ cnt += 1;
+ Some(Dropper::new(&set, id))
+ } else {
+ None
+ }
+ }),
+ 4
+ );
+ assert_eq!(cnt, 4);
+ assert_eq!(cnt, set.borrow().len());
+
+ assert_eq!(
+ cons.pop_each(
+ |_| {
+ cnt -= 1;
+ true
+ },
+ Some(2)
+ ),
+ 2
+ );
+ assert_eq!(cnt, 2);
+ assert_eq!(cnt, set.borrow().len());
+
+ assert_eq!(
+ prod.push_each(|| {
+ id += 1;
+ cnt += 1;
+ Some(Dropper::new(&set, id))
+ }),
+ 3
+ );
+ assert_eq!(cnt, 5);
+ assert_eq!(cnt, set.borrow().len());
+
+ assert_eq!(
+ cons.pop_each(
+ |_| {
+ cnt -= 1;
+ true
+ },
+ None
+ ),
+ 5
+ );
+ assert_eq!(cnt, 0);
+ assert_eq!(cnt, set.borrow().len());
+
+ assert_eq!(
+ prod.push_each(|| {
+ id += 1;
+ cnt += 1;
+ Some(Dropper::new(&set, id))
+ }),
+ 5
+ );
+ assert_eq!(cnt, 5);
+ assert_eq!(cnt, set.borrow().len());
+ }
+
+ assert_eq!(set.borrow().len(), 0);
+}
+
+/// Test the `pop_each` with internal function that returns false
+#[test]
+fn pop_each_test1() {
+ let cap = 10usize;
+ let (mut producer, mut consumer) = RingBuffer::new(cap).split();
+
+ for i in 0..cap {
+ producer.push((i, vec![0u8; 1000])).unwrap();
+ }
+
+ for _ in 0..cap {
+ let removed = consumer.pop_each(|_val| -> bool { false }, None);
+ assert_eq!(removed, 1);
+ }
+
+ assert_eq!(consumer.len(), 0);
+}
+
+/// Test the `pop_each` with capped pop
+#[test]
+fn pop_each_test2() {
+ let cap = 10usize;
+ let (mut producer, mut consumer) = RingBuffer::new(cap).split();
+
+ for i in 0..cap {
+ producer.push((i, vec![0u8; 1000])).unwrap();
+ }
+
+ for _ in 0..cap {
+ let removed = consumer.pop_each(|_val| -> bool { true }, Some(1));
+ assert_eq!(removed, 1);
+ }
+
+ assert_eq!(consumer.len(), 0);
+}
+
+/// Test the `push_each` with internal function that adds only 1 element.
+#[test]
+fn push_each_test1() {
+ let cap = 10usize;
+ let (mut producer, mut consumer) = RingBuffer::new(cap).split();
+
+ for i in 0..cap {
+ let mut count = 0;
+ // Add 1 element at a time
+ let added = producer.push_each(|| -> Option<(usize, Vec<u8>)> {
+ if count == 0 {
+ count += 1;
+ Some((i, vec![0u8; 1000]))
+ } else {
+ None
+ }
+ });
+ assert_eq!(added, 1);
+ }
+
+ for _ in 0..cap {
+ consumer.pop().unwrap();
+ }
+
+ assert_eq!(consumer.len(), 0);
+}
+
+/// Test the `push_each` with split internal buffer
+#[test]
+fn push_each_test2() {
+ let cap = 10usize;
+ let cap_half = 5usize;
+ let (mut producer, mut consumer) = RingBuffer::new(cap).split();
+
+ // Fill the entire buffer
+ for i in 0..cap {
+ producer.push((i, vec![0u8; 1000])).unwrap();
+ }
+
+ // Remove half elements
+ for _ in 0..cap_half {
+ consumer.pop().unwrap();
+ }
+
+ // Re add half elements one by one and check the return count.
+ for i in 0..cap_half {
+ let mut count = 0;
+ // Add 1 element at a time
+ let added = producer.push_each(|| -> Option<(usize, Vec<u8>)> {
+ if count == 0 {
+ count += 1;
+ Some((i, vec![0u8; 1000]))
+ } else {
+ None
+ }
+ });
+ assert_eq!(added, 1);
+ }
+
+ for _ in 0..cap {
+ consumer.pop().unwrap();
+ }
+
+ assert_eq!(consumer.len(), 0);
+}