bufferring 0.0.2

Ring buffers for Rust
Documentation
#![cfg(test)]

use proptest::prelude::*;

use crate::{RingBuffer, MaskingBuffer, storage::HeapStorage};
use super::prop::*;

prop_compose! {
    fn arb_heap_index(arb_item: impl Strategy<Value = i32>)
                     ((buf, items) in arb_heap_paired(arb_item))
                     (i in (0 .. items.len()), (buf, its) in Just((buf, items)))
    -> (usize, MaskingBuffer<HeapStorage<i32>>, Vec<i32>) { (i, buf, its) }
}

proptest! {
    #[test]
    fn test_arb((mut buf, items) in arb_heap_paired(any::<i32>())) {
        // Test the properties of an arbitrary buffer, using the list of items
        // that have been added to it.

        prop_assert_eq!(buf.len(), items.len());
        prop_assert_eq!(buf.is_empty(), buf.len() == 0);
        prop_assert_eq!(buf.is_full(), buf.len() == buf.cap());

        for i in 0 .. buf.len() {
            // SAFETY: `i` is guaranteed to be within `buf.len()`.
            prop_assert_eq!(items[i], unsafe { *buf.get_disjoint_mut(i) });
        }

        prop_assert_eq!(&items, &buf.iter()
                .map(|x| *x).collect::<Vec<_>>());

        prop_assert_eq!(&items, &buf.iter_mut()
                .map(|x| *x).collect::<Vec<_>>());

        prop_assert_eq!(&items, &buf.drain().collect::<Vec<_>>());
    }

    #[test]
    fn test_arb_empty(mut buf in arb_heap_empty::<i32>()) {
        // Test the properties of an arbitrary empty buffer.

        prop_assert_eq!(buf.len(), 0);
        prop_assert!(buf.iter().eq([].iter()));
        prop_assert!(buf.iter_mut().eq([].iter_mut()));
        prop_assert!(buf.is_empty());
        prop_assert!(!buf.is_full());
    }

    #[test]
    fn test_get(
        (mut buf, items) in arb_heap_paired(any::<i32>()),
        index in any::<usize>(),
    ) {
        // Test that `buf.get()` and `buf.get_mut()` return the correct elements
        // (or `None`) for any possible index.

        let expected = items.get(index).map(|x| *x);
        prop_assert_eq!(expected, buf.get(index).map(|x| *x));
        prop_assert_eq!(expected, buf.get_mut(index).map(|x| *x));
    }

    #[test]
    fn test_enqueue(
        (mut buf, mut old_items) in arb_heap_paired(any::<i32>()),
        item in any::<i32>(),
    ) {
        // Test that a newly-enqueued item shows up in `iter()` - and that none
        // of the other items are affected.

        old_items.push(item);
        let mut new_items = Vec::with_capacity(old_items.len());
        new_items.extend(buf.enqueue(item).into_iter());
        new_items.extend(buf.iter().copied());
        prop_assert_eq!(old_items, new_items);
    }

    #[test]
    fn test_dequeue((mut buf, old_items) in arb_heap_paired(any::<i32>())) {
        // Test that dequeueing removes an item without affecting others.

        let mut new_items = Vec::with_capacity(old_items.len());
        new_items.extend(buf.dequeue().into_iter());
        new_items.extend(buf.iter().copied());
        prop_assert_eq!(old_items, new_items);
    }

    #[test]
    fn test_skip_one((mut buf, old_items) in arb_heap_paired(any::<i32>())) {
        // Test that `skip_one()` removes an item without affecting others.

        let mut new_items = Vec::with_capacity(old_items.len() - 1);
        new_items.extend(buf.get(0).copied().into_iter());
        buf.skip_one();
        new_items.extend(buf.iter().copied());
        prop_assert_eq!(old_items, new_items);
    }

    #[test]
    fn test_skip((num, mut buf, old_items) in arb_heap_index(any::<i32>())) {
        // Test that `skip()` removes items without affecting others.

        buf.skip(num);
        let new_items = buf.iter().copied().collect::<Vec<_>>();
        prop_assert_eq!(&old_items[num ..], &new_items[..]);
    }
}