Radish alpha
h
rad:z3gqcJUoA1n9HaHKufZs5FCSGazv5
Radicle Heartwood Protocol & Stack
Radicle
Git
heartwood crates radicle-protocol src fetcher test queue properties capacity.rs
use qcheck_macros::quickcheck;

use crate::fetcher::test::queue::helpers::*;
use crate::fetcher::{MaxQueueSize, state::Enqueue};
use crate::fetcher::{Queue, QueuedFetch};

#[quickcheck]
fn bounded(max_size: MaxQueueSize, num_enqueues: u8) -> bool {
    let mut queue = Queue::new(max_size);

    for _ in 0..num_enqueues {
        let _ = queue.enqueue(create_fetch());

        // Invariant: length never exceeds capacity
        if queue.len() > max_size.as_usize() {
            return false;
        }
    }
    true
}

#[quickcheck]
fn rejection(max_size: MaxQueueSize) -> bool {
    let mut queue = Queue::new(max_size);

    // Fill to capacity with unique items
    let items = unique_fetches(max_size.as_usize());
    for item in &items {
        if queue.enqueue(item.clone()) != Enqueue::Queued {
            return false;
        }
    }

    // Next enqueue of a NEW item must be rejected
    matches!(queue.enqueue(create_fetch()), Enqueue::CapacityReached(_))
}

#[quickcheck]
fn restored_after_dequeue(max_size: MaxQueueSize, dequeue_count: u8) -> bool {
    let mut queue = Queue::new(max_size);

    // Fill to capacity
    for _ in 0..max_size.as_usize() {
        let _ = queue.enqueue(create_fetch());
    }

    // Dequeue some items
    let to_dequeue = (dequeue_count as usize).min(max_size.as_usize());
    for _ in 0..to_dequeue {
        let _ = queue.dequeue();
    }

    // Should be able to enqueue exactly that many items again
    for _ in 0..to_dequeue {
        if queue.enqueue(create_fetch()) != Enqueue::Queued {
            return false;
        }
    }

    // Next enqueue should fail
    matches!(queue.enqueue(create_fetch()), Enqueue::CapacityReached(_))
}

#[quickcheck]
fn capacity_reached_returns_same_item(item: QueuedFetch) -> bool {
    let mut queue = create_queue(1);
    let _ = queue.enqueue(create_fetch()); // Fill the queue

    match queue.enqueue(item.clone()) {
        Enqueue::CapacityReached(returned) => returned == item,
        Enqueue::Merged => true, // If same rid, merge takes precedence
        _ => false,
    }
}