use {
super::super::*,
crate::arch::sync::Mutex,
std::sync::{
Arc,
atomic::{AtomicUsize, Ordering},
},
};
#[test]
fn test_new() {
let queue = WorkQueue::new();
assert_eq!(queue.capacity(), WORK_QUEUE_DEFAULT_CAPACITY);
assert!(queue.is_empty());
assert_eq!(queue.len(), 0);
assert_eq!(queue.dropped_count(), 0);
}
#[test]
fn test_with_capacity() {
let queue = WorkQueue::with_capacity(100);
assert_eq!(queue.capacity(), 100);
}
#[test]
fn test_with_capacity_clamped() {
let queue = WorkQueue::with_capacity(WORK_QUEUE_MAX_CAPACITY + 1000);
assert_eq!(queue.capacity(), WORK_QUEUE_MAX_CAPACITY);
}
#[test]
fn test_push_and_pop() {
let queue = WorkQueue::new();
let counter = Arc::new(AtomicUsize::new(0));
let counter_clone = Arc::clone(&counter);
queue.push(Task::new(move || {
counter_clone.fetch_add(1, Ordering::SeqCst);
}));
assert_eq!(queue.len(), 1);
assert!(!queue.is_empty());
let mut task = queue.try_pop().unwrap();
assert!(task.execute().is_ok());
assert_eq!(counter.load(Ordering::SeqCst), 1);
assert!(queue.is_empty());
}
#[test]
fn test_fifo_order() {
let queue = WorkQueue::new();
let order = Arc::new(Mutex::new(Vec::new()));
for i in 0..5 {
let order_clone = Arc::clone(&order);
queue.push(Task::new(move || {
order_clone.lock().push(i);
}));
}
while let Some(mut task) = queue.try_pop() {
task.execute().ok();
}
let result = order.lock().clone();
assert_eq!(result, vec![0, 1, 2, 3, 4]);
}
#[test]
fn test_overflow() {
let queue = WorkQueue::with_capacity(3);
assert!(queue.push(Task::new(|| {})));
assert!(queue.push(Task::new(|| {})));
assert!(queue.push(Task::new(|| {})));
assert!(!queue.push(Task::new(|| {}))); assert!(!queue.push(Task::new(|| {})));
assert_eq!(queue.len(), 3);
assert_eq!(queue.dropped_count(), 2);
}
#[test]
fn test_overflow_recovery() {
let queue = WorkQueue::with_capacity(2);
queue.push(Task::new(|| {}));
queue.push(Task::new(|| {}));
assert!(!queue.push(Task::new(|| {})));
let _ = queue.try_pop(); assert!(queue.push(Task::new(|| {}))); assert_eq!(queue.len(), 2);
}
#[test]
fn test_drain() {
let queue = WorkQueue::new();
for _ in 0..5 {
queue.push(Task::new(|| {}));
}
let tasks = queue.drain();
assert_eq!(tasks.len(), 5);
assert!(queue.is_empty());
}
#[test]
fn test_drain_empty() {
let queue = WorkQueue::new();
let tasks = queue.drain();
assert!(tasks.is_empty());
}
#[test]
fn test_process_pending() {
let queue = WorkQueue::new();
let counter = Arc::new(AtomicUsize::new(0));
for _ in 0..10 {
let counter_clone = Arc::clone(&counter);
queue.push(Task::new(move || {
counter_clone.fetch_add(1, Ordering::SeqCst);
}));
}
let processed = queue.process_pending(5);
assert_eq!(processed, 5);
assert_eq!(counter.load(Ordering::SeqCst), 5);
assert_eq!(queue.len(), 5);
let processed = queue.process_pending(10);
assert_eq!(processed, 5);
assert_eq!(counter.load(Ordering::SeqCst), 10);
assert!(queue.is_empty());
}
#[test]
fn test_process_pending_empty() {
let queue = WorkQueue::new();
let processed = queue.process_pending(10);
assert_eq!(processed, 0);
}
#[test]
fn test_clear() {
let queue = WorkQueue::new();
for _ in 0..5 {
queue.push(Task::new(|| {}));
}
let cleared = queue.clear();
assert_eq!(cleared, 5);
assert!(queue.is_empty());
}
#[test]
#[cfg_attr(coverage_nightly, coverage(off))]
fn test_debug() {
let queue = WorkQueue::with_capacity(100);
queue.push(Task::new(|| {}));
let debug_str = format!("{queue:?}");
assert!(debug_str.contains("WorkQueue"));
assert!(debug_str.contains("len"));
assert!(debug_str.contains("capacity"));
}
#[test]
fn test_concurrent_push() {
use std::thread;
let queue = Arc::new(WorkQueue::with_capacity(1000));
let mut handles = vec![];
for _ in 0..10 {
let queue_clone = Arc::clone(&queue);
handles.push(thread::spawn(move || {
for _ in 0..50 {
queue_clone.push(Task::new(|| {}));
}
}));
}
for handle in handles {
handle.join().unwrap();
}
assert_eq!(queue.len(), 500);
}
#[test]
fn test_work_queue_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<WorkQueue>();
}
#[test]
fn test_work_queue_default() {
let queue = WorkQueue::default();
assert_eq!(queue.capacity(), WORK_QUEUE_DEFAULT_CAPACITY);
assert!(queue.is_empty());
}
#[test]
fn test_clear_returns_count() {
let queue = WorkQueue::new();
queue.push(Task::new(|| {}));
queue.push(Task::new(|| {}));
queue.push(Task::new(|| {}));
let cleared = queue.clear();
assert_eq!(cleared, 3);
assert!(queue.is_empty());
let cleared_empty = queue.clear();
assert_eq!(cleared_empty, 0);
}
#[test]
fn test_process_pending_limit_exceeds_queue() {
let queue = WorkQueue::new();
let counter = Arc::new(AtomicUsize::new(0));
for _ in 0..3 {
let counter_clone = Arc::clone(&counter);
queue.push(Task::new(move || {
counter_clone.fetch_add(1, Ordering::SeqCst);
}));
}
let processed = queue.process_pending(100);
assert_eq!(processed, 3);
assert_eq!(counter.load(Ordering::SeqCst), 3);
assert!(queue.is_empty());
}
#[test]
#[cfg_attr(coverage_nightly, coverage(off))]
fn test_debug_with_dropped() {
let queue = WorkQueue::with_capacity(1);
queue.push(Task::new(|| {}));
queue.push(Task::new(|| {})); let debug_str = format!("{queue:?}");
assert!(debug_str.contains("dropped"));
assert!(debug_str.contains('1')); }
#[test]
fn test_try_pop_empty_returns_none() {
let queue = WorkQueue::new();
assert!(queue.try_pop().is_none());
}
#[test]
fn test_process_pending_zero_limit() {
let queue = WorkQueue::new();
queue.push(Task::new(|| {}));
let processed = queue.process_pending(0);
assert_eq!(processed, 0);
assert_eq!(queue.len(), 1);
}
#[test]
fn test_with_capacity_zero() {
let queue = WorkQueue::with_capacity(0);
assert_eq!(queue.capacity(), 0);
assert!(!queue.push(Task::new(|| {})));
assert_eq!(queue.dropped_count(), 1);
}
#[test]
fn test_push_overflow_capacity_one() {
let queue = WorkQueue::with_capacity(1);
assert!(queue.push(Task::new(|| {}))); assert!(!queue.push(Task::new(|| {}))); assert_eq!(queue.dropped_count(), 1);
assert_eq!(queue.len(), 1);
}
#[test]
fn test_process_pending_breaks_on_empty_queue() {
let queue = WorkQueue::with_capacity(2);
queue.push(Task::new(|| {}));
queue.push(Task::new(|| {}));
let processed = queue.process_pending(100);
assert_eq!(processed, 2);
assert!(queue.is_empty());
}